Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7b5e25b8 authored by Joerg Roedel's avatar Joerg Roedel
Browse files

iommu/amd: Use trylock to aquire bitmap_lock



First search for a non-contended aperture with trylock
before spinning.

Signed-off-by: default avatarJoerg Roedel <jroedel@suse.de>
parent 5f6bed50
Loading
Loading
Loading
Loading
+17 −3
Original line number Diff line number Diff line
@@ -1542,7 +1542,8 @@ static dma_addr_t dma_ops_aperture_alloc(struct dma_ops_domain *dom,
					 unsigned long pages,
					 unsigned long dma_mask,
					 unsigned long boundary_size,
					 unsigned long align_mask)
					 unsigned long align_mask,
					 bool trylock)
{
	unsigned long offset, limit, flags;
	dma_addr_t address;
@@ -1552,7 +1553,13 @@ static dma_addr_t dma_ops_aperture_alloc(struct dma_ops_domain *dom,
	limit  = iommu_device_max_index(APERTURE_RANGE_PAGES, offset,
					dma_mask >> PAGE_SHIFT);

	if (trylock) {
		if (!spin_trylock_irqsave(&range->bitmap_lock, flags))
			return -1;
	} else {
		spin_lock_irqsave(&range->bitmap_lock, flags);
	}

	address = iommu_area_alloc(range->bitmap, limit, range->next_bit,
				   pages, offset, boundary_size, align_mask);
	if (address == -1) {
@@ -1584,12 +1591,14 @@ static unsigned long dma_ops_area_alloc(struct device *dev,
{
	unsigned long boundary_size, mask;
	unsigned long address = -1;
	bool first = true;
	u32 start, i;

	preempt_disable();

	mask = dma_get_seg_boundary(dev);

again:
	start = this_cpu_read(*dom->next_index);

	/* Sanity check - is it really necessary? */
@@ -1614,7 +1623,7 @@ static unsigned long dma_ops_area_alloc(struct device *dev,

		address = dma_ops_aperture_alloc(dom, range, pages,
						 dma_mask, boundary_size,
						 align_mask);
						 align_mask, first);
		if (address != -1) {
			address = range->offset + (address << PAGE_SHIFT);
			this_cpu_write(*dom->next_index, index);
@@ -1622,6 +1631,11 @@ static unsigned long dma_ops_area_alloc(struct device *dev,
		}
	}

	if (address == -1 && first) {
		first = false;
		goto again;
	}

	preempt_enable();

	return address;