All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Huang, Honglei" <honghuan@amd.com>
To: Leon Romanovsky <leonro@nvidia.com>
Cc: robin.murphy@arm.com, joro@8bytes.org, will@kernel.org,
	m.szyprowski@samsung.com, iommu@lists.linux.dev,
	linux-kernel@vger.kernel.org, Ray.Huang@amd.com
Subject: Re: [PATCH] iommu/dma: free the entire IOVA reservation in dma_iova_destroy()
Date: Fri, 3 Jul 2026 11:37:52 +0800	[thread overview]
Message-ID: <2a875f28-e334-4349-84a0-51998baf1f40@amd.com> (raw)
In-Reply-To: <20260702102453.GE65299@unreal>



On 7/2/2026 6:24 PM, Leon Romanovsky wrote:
> On Wed, Jul 01, 2026 at 05:20:33PM +0800, Honglei Huang wrote:
>> dma_iova_try_alloc() reserves IOVA for the whole requested size and
>> records it in state->__size, but callers may subsequently link only a
>> part of that reservation, for example the drm_gpusvm mixed range case,
>> where a device page range is linked incrementally.
>>
>> The doc for dma_iova_destroy() is:
>>
>>    "Unlink the IOVA range up to @mapped_len and free the entire IOVA
>>     space."
>>
>> However __iommu_dma_iova_unlink() computed the amount of IOVA to free
>> from @mapped_len rather than from the full reservation. When the
>> reservation is larger than the linked length, the tail
>> [mapped_len, reserved size] is never returned to the allocator and
>> is leaked, contrary to the documented contract.
>>
>> Free the whole reservation using dma_iova_size(), mirroring
>> dma_iova_free(). The unmap step still operates on @mapped_len only, and
>> the same iotlb_gather is reused so a single IOTLB flush is performed.
>>
>> Fixes: 433a76207dcf ("dma-mapping: Implement link/unlink ranges API")
>> Cc: stable@vger.kernel.org
>> Signed-off-by: Honglei Huang <honghuan@amd.com>
>> ---
>>   drivers/iommu/dma-iommu.c | 5 ++++-
>>   1 file changed, 4 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
>> index 9abaec0703e..bb29c82d1c8 100644
>> --- a/drivers/iommu/dma-iommu.c
>> +++ b/drivers/iommu/dma-iommu.c
>> @@ -2096,8 +2096,11 @@ static void __iommu_dma_iova_unlink(struct device *dev,
>>   
>>   	if (!iotlb_gather.queued)
>>   		iommu_iotlb_sync(domain, &iotlb_gather);
>> -	if (free_iova)
>> +	if (free_iova) {
>> +		/* Free the whole reservation, not just the linked @size. */
>> +		size = iova_align(iovad, dma_iova_size(state) + iova_start_pad);
>>   		iommu_dma_free_iova(domain, addr, size, &iotlb_gather);
>> +	}
> 
> Probably the best change will be something like this:

Thanks for the review and for the shown rework, that's much cleaner
than my original approach.

Based on the your code, I have made some modifications to the 
compilation issues and will send V2.

And the v2 is essentially your diff, I wasn't sure which attribution 
you'd prefer:

   - Suggested-by, what I used in v2
	or
   - Co-developed-by: + your Signed-off-by.

Just let me know, will adjust in V3.

Regards,
Honglei


> 
> diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
> index 9abaec0703ef..56173e24c8cc 100644
> --- a/drivers/iommu/dma-iommu.c
> +++ b/drivers/iommu/dma-iommu.c
> @@ -2068,10 +2068,20 @@ static void iommu_dma_iova_unlink_range_slow(struct device *dev,
>   		arch_sync_dma_flush();
>   }
>   
> -static void __iommu_dma_iova_unlink(struct device *dev,
> -		struct dma_iova_state *state, size_t offset, size_t size,
> -		enum dma_data_direction dir, unsigned long attrs,
> -		bool free_iova)
> +/**
> + * dma_iova_unlink - Unlink a range of IOVA space
> + * @dev: DMA device
> + * @state: IOVA state
> + * @offset: offset into the IOVA state to unlink
> + * @size: size of the buffer
> + * @dir: DMA direction
> + * @attrs: attributes of mapping properties
> + *
> + * Unlink a range of IOVA space for the given IOVA state.
> + */
> +void dma_iova_unlink(struct device *dev, struct dma_iova_state *state,
> +		size_t offset, size_t size, enum dma_data_direction dir,
> +		unsigned long attrs)
>   {
>   	struct iommu_domain *domain = iommu_get_dma_domain(dev);
>   	struct iommu_dma_cookie *cookie = domain->iova_cookie;
> @@ -2096,26 +2106,6 @@ static void __iommu_dma_iova_unlink(struct device *dev,
>   
>   	if (!iotlb_gather.queued)
>   		iommu_iotlb_sync(domain, &iotlb_gather);
> -	if (free_iova)
> -		iommu_dma_free_iova(domain, addr, size, &iotlb_gather);
> -}
> -
> -/**
> - * dma_iova_unlink - Unlink a range of IOVA space
> - * @dev: DMA device
> - * @state: IOVA state
> - * @offset: offset into the IOVA state to unlink
> - * @size: size of the buffer
> - * @dir: DMA direction
> - * @attrs: attributes of mapping properties
> - *
> - * Unlink a range of IOVA space for the given IOVA state.
> - */
> -void dma_iova_unlink(struct device *dev, struct dma_iova_state *state,
> -		size_t offset, size_t size, enum dma_data_direction dir,
> -		unsigned long attrs)
> -{
> -	 __iommu_dma_iova_unlink(dev, state, offset, size, dir, attrs, false);
>   }
>   EXPORT_SYMBOL_GPL(dma_iova_unlink);
>   
> @@ -2136,14 +2126,13 @@ void dma_iova_destroy(struct device *dev, struct dma_iova_state *state,
>   		unsigned long attrs)
>   {
>   	if (mapped_len)
> -		__iommu_dma_iova_unlink(dev, state, 0, mapped_len, dir, attrs,
> -				true);
> -	else
> -		/*
> -		 * We can be here if first call to dma_iova_link() failed and
> -		 * there is nothing to unlink, so let's be more clear.
> -		 */
> -		dma_iova_free(dev, state);
> +		dma_iova_unlink(dev, state, 0, mapped_len, dir, attrs);
> +
> +	/*
> +	 * We can be here if first call to dma_iova_link() failed and
> +	 * there is nothing to unlink, so let's be more clear.
> +	 */
> +	dma_iova_free(dev, state);
>   }
>   EXPORT_SYMBOL_GPL(dma_iova_destroy);
>   
> 
>>   }
>>   
>>   /**
>>
>> base-commit: dc59e4fea9d83f03bad6bddf3fa2e52491777482
>> -- 
>> 2.34.1
>>


      reply	other threads:[~2026-07-03  3:38 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-01  9:20 [PATCH] iommu/dma: free the entire IOVA reservation in dma_iova_destroy() Honglei Huang
2026-07-01 12:36 ` Robin Murphy
2026-07-01 19:08   ` Leon Romanovsky
2026-07-03  3:31   ` Huang, Honglei
2026-07-01 19:09 ` Leon Romanovsky
2026-07-02 10:24 ` Leon Romanovsky
2026-07-03  3:37   ` Huang, Honglei [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=2a875f28-e334-4349-84a0-51998baf1f40@amd.com \
    --to=honghuan@amd.com \
    --cc=Ray.Huang@amd.com \
    --cc=iommu@lists.linux.dev \
    --cc=joro@8bytes.org \
    --cc=leonro@nvidia.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=m.szyprowski@samsung.com \
    --cc=robin.murphy@arm.com \
    --cc=will@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.