Unverified Commit cde89521 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!8535 v4 Fix soft lockup in stress test

Merge Pull Request from: @ci-robot 
 
PR sync from: Zhang Zekun <zhangzekun11@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/VJNUHVQB7FLGQZZGXMXZQVBO2WMLFN3H/ 
speed up the speed of freeing iova and add a cond_resched().

v4:
Add fix tags.

v3:
Fix check format warning.

v2:
add a cover letter to generate a pr.


Zhang Zekun (2):
  iommu/iova: free iovas on each cpu in flush queue
  iommu/iova: Try to schedule out when free iova too long


-- 
2.17.1
 
https://gitee.com/openeuler/kernel/issues/I9SOOM 
 
Link:https://gitee.com/openeuler/kernel/pulls/8535

 

Reviewed-by: default avatarWeilong Chen <chenweilong@huawei.com>
Reviewed-by: default avatarJialin Zhang <zhangjialin11@huawei.com>
Signed-off-by: default avatarJialin Zhang <zhangjialin11@huawei.com>
parents f3136395 c5f0d3e1
Loading
Loading
Loading
Loading
+25 −16
Original line number Diff line number Diff line
@@ -18,7 +18,7 @@

static bool iova_rcache_insert(struct iova_domain *iovad,
			       unsigned long pfn,
			       unsigned long size);
			       unsigned long size, int cpu);
static unsigned long iova_rcache_get(struct iova_domain *iovad,
				     unsigned long size,
				     unsigned long limit_pfn);
@@ -77,7 +77,7 @@ static void free_iova_flush_queue(struct iova_domain *iovad)
	iovad->entry_dtor = NULL;
}

static void fq_ring_free(struct iova_domain *iovad, struct iova_fq *fq);
static void fq_ring_free(struct iova_domain *iovad, struct iova_fq *fq, int cpu);
static void free_iova_work_func(struct work_struct *work)
{
	struct iova_domain *iovad;
@@ -90,8 +90,9 @@ static void free_iova_work_func(struct work_struct *work)

		fq = per_cpu_ptr(iovad->fq, cpu);
		spin_lock_irqsave(&fq->lock, flags);
		fq_ring_free(iovad, fq);
		fq_ring_free(iovad, fq, cpu);
		spin_unlock_irqrestore(&fq->lock, flags);
		cond_resched();
	}
}

@@ -459,6 +460,15 @@ alloc_iova_fast(struct iova_domain *iovad, unsigned long size,
}
EXPORT_SYMBOL_GPL(alloc_iova_fast);

static void
free_iova_fast_internal(struct iova_domain *iovad, unsigned long pfn, unsigned long size, int cpu)
{
	if (iova_rcache_insert(iovad, pfn, size, cpu))
		return;

	free_iova(iovad, pfn);
}

/**
 * free_iova_fast - free iova pfn range into rcache
 * @iovad: - iova domain in question.
@@ -470,13 +480,11 @@ EXPORT_SYMBOL_GPL(alloc_iova_fast);
void
free_iova_fast(struct iova_domain *iovad, unsigned long pfn, unsigned long size)
{
	if (iova_rcache_insert(iovad, pfn, size))
		return;

	free_iova(iovad, pfn);
	free_iova_fast_internal(iovad, pfn, size, smp_processor_id());
}
EXPORT_SYMBOL_GPL(free_iova_fast);


#define fq_ring_for_each(i, fq) \
	for ((i) = (fq)->head; (i) != (fq)->tail; (i) = ((i) + 1) % IOVA_FQ_SIZE)

@@ -497,7 +505,7 @@ static inline unsigned fq_ring_add(struct iova_fq *fq)
	return idx;
}

static void fq_ring_free(struct iova_domain *iovad, struct iova_fq *fq)
static void fq_ring_free(struct iova_domain *iovad, struct iova_fq *fq, int cpu)
{
	u64 counter = atomic64_read(&iovad->fq_flush_finish_cnt);
	unsigned idx;
@@ -512,9 +520,9 @@ static void fq_ring_free(struct iova_domain *iovad, struct iova_fq *fq)
		if (iovad->entry_dtor)
			iovad->entry_dtor(fq->entries[idx].data);

		free_iova_fast(iovad,
		free_iova_fast_internal(iovad,
			       fq->entries[idx].iova_pfn,
			       fq->entries[idx].pages);
			       fq->entries[idx].pages, cpu);

		fq->head = (fq->head + 1) % IOVA_FQ_SIZE;
	}
@@ -565,6 +573,7 @@ void queue_iova(struct iova_domain *iovad,
	struct iova_fq *fq = raw_cpu_ptr(iovad->fq);
	unsigned long flags;
	unsigned idx;
	int cpu = smp_processor_id();

	/*
	 * Order against the IOMMU driver's pagetable update from unmapping
@@ -580,11 +589,11 @@ void queue_iova(struct iova_domain *iovad,
	 * flushed out on another CPU. This makes the fq_full() check below less
	 * likely to be true.
	 */
	fq_ring_free(iovad, fq);
	fq_ring_free(iovad, fq, cpu);

	if (fq_full(fq)) {
		iova_domain_flush(iovad);
		fq_ring_free(iovad, fq);
		fq_ring_free(iovad, fq, cpu);
	}

	idx = fq_ring_add(fq);
@@ -957,13 +966,13 @@ static void init_iova_rcaches(struct iova_domain *iovad)
 */
static bool __iova_rcache_insert(struct iova_domain *iovad,
				 struct iova_rcache *rcache,
				 unsigned long iova_pfn)
				 unsigned long iova_pfn, int cpu)
{
	struct iova_cpu_rcache *cpu_rcache;
	bool can_insert = false;
	unsigned long flags;

	cpu_rcache = raw_cpu_ptr(rcache->cpu_rcaches);
	cpu_rcache = per_cpu_ptr(rcache->cpu_rcaches, cpu);
	spin_lock_irqsave(&cpu_rcache->lock, flags);

	if (!iova_magazine_full(cpu_rcache->loaded)) {
@@ -994,14 +1003,14 @@ static bool __iova_rcache_insert(struct iova_domain *iovad,
}

static bool iova_rcache_insert(struct iova_domain *iovad, unsigned long pfn,
			       unsigned long size)
			       unsigned long size, int cpu)
{
	unsigned int log_size = order_base_2(size);

	if (log_size >= IOVA_RANGE_CACHE_MAX_SIZE)
		return false;

	return __iova_rcache_insert(iovad, &iovad->rcaches[log_size], pfn);
	return __iova_rcache_insert(iovad, &iovad->rcaches[log_size], pfn, cpu);
}

/*