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

!5334 v4 iommu/iova: avoid softlockup in fq_flush_timeout

parents 1b4212c6 0289343f
Loading
Loading
Loading
Loading
+20 −7
Original line number Diff line number Diff line
@@ -85,6 +85,8 @@ struct iommu_dma_cookie {
	/* Options for dma-iommu use */
	struct iommu_dma_options	options;
	struct mutex			mutex;

	struct work_struct free_iova_work;
};

static DEFINE_STATIC_KEY_FALSE(iommu_deferred_attach_enabled);
@@ -184,17 +186,11 @@ static void fq_flush_iotlb(struct iommu_dma_cookie *cookie)
static void fq_flush_timeout(struct timer_list *t)
{
	struct iommu_dma_cookie *cookie = from_timer(cookie, t, fq_timer);
	int cpu;

	atomic_set(&cookie->fq_timer_on, 0);
	fq_flush_iotlb(cookie);

	if (cookie->options.qt == IOMMU_DMA_OPTS_SINGLE_QUEUE) {
		fq_ring_free(cookie, cookie->single_fq);
	} else {
		for_each_possible_cpu(cpu)
			fq_ring_free(cookie, per_cpu_ptr(cookie->percpu_fq, cpu));
	}
	schedule_work(&cookie->free_iova_work);
}

static void queue_iova(struct iommu_dma_cookie *cookie,
@@ -279,6 +275,7 @@ static void iommu_dma_free_fq(struct iommu_dma_cookie *cookie)
		return;

	del_timer_sync(&cookie->fq_timer);
	flush_work(&cookie->free_iova_work);
	if (cookie->options.qt == IOMMU_DMA_OPTS_SINGLE_QUEUE)
		iommu_dma_free_fq_single(cookie->single_fq);
	else
@@ -330,6 +327,21 @@ static int iommu_dma_init_fq_percpu(struct iommu_dma_cookie *cookie)
	return 0;
}

static void free_iova_work_func(struct work_struct *work)
{
	struct iommu_dma_cookie *cookie;
	int cpu;

	cookie = container_of(work, struct iommu_dma_cookie, free_iova_work);
	if (cookie->options.qt == IOMMU_DMA_OPTS_SINGLE_QUEUE) {
		fq_ring_free(cookie, cookie->single_fq);
	} else {
		for_each_possible_cpu(cpu)
			fq_ring_free(cookie, per_cpu_ptr(cookie->percpu_fq, cpu));
	}

}

/* sysfs updates are serialised by the mutex of the group owning @domain */
int iommu_dma_init_fq(struct iommu_domain *domain)
{
@@ -352,6 +364,7 @@ int iommu_dma_init_fq(struct iommu_domain *domain)
		return -ENOMEM;
	}

	INIT_WORK(&cookie->free_iova_work, free_iova_work_func);
	timer_setup(&cookie->fq_timer, fq_flush_timeout, 0);
	atomic_set(&cookie->fq_timer_on, 0);
	/*