From 9af17ff47fa68358d5a8d02fa72c46458f386ffb Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 3 Apr 2020 11:23:39 +0200 Subject: [PATCH] 4.9-stable patches added patches: blk-mq-sync-the-update-nr_hw_queues-with-blk_mq_queue_tag_busy_iter.patch drm-etnaviv-replace-mmu-flush-marker-with-flush-sequence.patch --- ...eues-with-blk_mq_queue_tag_busy_iter.patch | 76 ++++++++++ ...mmu-flush-marker-with-flush-sequence.patch | 138 ++++++++++++++++++ queue-4.9/series | 2 + 3 files changed, 216 insertions(+) create mode 100644 queue-4.9/blk-mq-sync-the-update-nr_hw_queues-with-blk_mq_queue_tag_busy_iter.patch create mode 100644 queue-4.9/drm-etnaviv-replace-mmu-flush-marker-with-flush-sequence.patch diff --git a/queue-4.9/blk-mq-sync-the-update-nr_hw_queues-with-blk_mq_queue_tag_busy_iter.patch b/queue-4.9/blk-mq-sync-the-update-nr_hw_queues-with-blk_mq_queue_tag_busy_iter.patch new file mode 100644 index 00000000000..cacbea8584b --- /dev/null +++ b/queue-4.9/blk-mq-sync-the-update-nr_hw_queues-with-blk_mq_queue_tag_busy_iter.patch @@ -0,0 +1,76 @@ +From f5bbbbe4d63577026f908a809f22f5fd5a90ea1f Mon Sep 17 00:00:00 2001 +From: Jianchao Wang +Date: Tue, 21 Aug 2018 15:15:04 +0800 +Subject: blk-mq: sync the update nr_hw_queues with blk_mq_queue_tag_busy_iter + +From: Jianchao Wang + +commit f5bbbbe4d63577026f908a809f22f5fd5a90ea1f upstream. + +For blk-mq, part_in_flight/rw will invoke blk_mq_in_flight/rw to +account the inflight requests. It will access the queue_hw_ctx and +nr_hw_queues w/o any protection. When updating nr_hw_queues and +blk_mq_in_flight/rw occur concurrently, panic comes up. + +Before update nr_hw_queues, the q will be frozen. So we could use +q_usage_counter to avoid the race. percpu_ref_is_zero is used here +so that we will not miss any in-flight request. The access to +nr_hw_queues and queue_hw_ctx in blk_mq_queue_tag_busy_iter are +under rcu critical section, __blk_mq_update_nr_hw_queues could use +synchronize_rcu to ensure the zeroed q_usage_counter to be globally +visible. + +Signed-off-by: Jianchao Wang +Reviewed-by: Ming Lei +Signed-off-by: Jens Axboe +Cc: Giuliano Procida +Signed-off-by: Greg Kroah-Hartman + +--- + block/blk-mq-tag.c | 14 +++++++++++++- + block/blk-mq.c | 4 ++++ + 2 files changed, 17 insertions(+), 1 deletion(-) + +--- a/block/blk-mq-tag.c ++++ b/block/blk-mq-tag.c +@@ -336,6 +336,18 @@ void blk_mq_queue_tag_busy_iter(struct r + struct blk_mq_hw_ctx *hctx; + int i; + ++ /* ++ * __blk_mq_update_nr_hw_queues will update the nr_hw_queues and ++ * queue_hw_ctx after freeze the queue. So we could use q_usage_counter ++ * to avoid race with it. __blk_mq_update_nr_hw_queues will users ++ * synchronize_rcu to ensure all of the users go out of the critical ++ * section below and see zeroed q_usage_counter. ++ */ ++ rcu_read_lock(); ++ if (percpu_ref_is_zero(&q->q_usage_counter)) { ++ rcu_read_unlock(); ++ return; ++ } + + queue_for_each_hw_ctx(q, hctx, i) { + struct blk_mq_tags *tags = hctx->tags; +@@ -351,7 +363,7 @@ void blk_mq_queue_tag_busy_iter(struct r + bt_for_each(hctx, &tags->breserved_tags, fn, priv, true); + bt_for_each(hctx, &tags->bitmap_tags, fn, priv, false); + } +- ++ rcu_read_unlock(); + } + + static unsigned int bt_unused_tags(const struct sbitmap_queue *bt) +--- a/block/blk-mq.c ++++ b/block/blk-mq.c +@@ -2346,6 +2346,10 @@ void blk_mq_update_nr_hw_queues(struct b + + list_for_each_entry(q, &set->tag_list, tag_set_list) + blk_mq_unfreeze_queue(q); ++ /* ++ * Sync with blk_mq_queue_tag_busy_iter. ++ */ ++ synchronize_rcu(); + } + EXPORT_SYMBOL_GPL(blk_mq_update_nr_hw_queues); + diff --git a/queue-4.9/drm-etnaviv-replace-mmu-flush-marker-with-flush-sequence.patch b/queue-4.9/drm-etnaviv-replace-mmu-flush-marker-with-flush-sequence.patch new file mode 100644 index 00000000000..a99f9d85af8 --- /dev/null +++ b/queue-4.9/drm-etnaviv-replace-mmu-flush-marker-with-flush-sequence.patch @@ -0,0 +1,138 @@ +From 4900dda90af2cb13bc1d4c12ce94b98acc8fe64e Mon Sep 17 00:00:00 2001 +From: Lucas Stach +Date: Fri, 5 Jul 2019 19:17:23 +0200 +Subject: drm/etnaviv: replace MMU flush marker with flush sequence +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Lucas Stach + +commit 4900dda90af2cb13bc1d4c12ce94b98acc8fe64e upstream. + +If a MMU is shared between multiple GPUs, all of them need to flush their +TLBs, so a single marker that gets reset on the first flush won't do. +Replace the flush marker with a sequence number, so that it's possible to +check if the TLB is in sync with the current page table state for each GPU. + +Signed-off-by: Lucas Stach +Reviewed-by: Philipp Zabel +Reviewed-by: Guido Günther +Signed-off-by: Robert Beckett +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/etnaviv/etnaviv_buffer.c | 10 ++++++---- + drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 2 +- + drivers/gpu/drm/etnaviv/etnaviv_gpu.h | 1 + + drivers/gpu/drm/etnaviv/etnaviv_mmu.c | 6 +++--- + drivers/gpu/drm/etnaviv/etnaviv_mmu.h | 2 +- + 5 files changed, 12 insertions(+), 9 deletions(-) + +--- a/drivers/gpu/drm/etnaviv/etnaviv_buffer.c ++++ b/drivers/gpu/drm/etnaviv/etnaviv_buffer.c +@@ -257,6 +257,8 @@ void etnaviv_buffer_queue(struct etnaviv + unsigned int waitlink_offset = buffer->user_size - 16; + u32 return_target, return_dwords; + u32 link_target, link_dwords; ++ unsigned int new_flush_seq = READ_ONCE(gpu->mmu->flush_seq); ++ bool need_flush = gpu->flush_seq != new_flush_seq; + + if (drm_debug & DRM_UT_DRIVER) + etnaviv_buffer_dump(gpu, buffer, 0, 0x50); +@@ -269,14 +271,14 @@ void etnaviv_buffer_queue(struct etnaviv + * need to append a mmu flush load state, followed by a new + * link to this buffer - a total of four additional words. + */ +- if (gpu->mmu->need_flush || gpu->switch_context) { ++ if (need_flush || gpu->switch_context) { + u32 target, extra_dwords; + + /* link command */ + extra_dwords = 1; + + /* flush command */ +- if (gpu->mmu->need_flush) { ++ if (need_flush) { + if (gpu->mmu->version == ETNAVIV_IOMMU_V1) + extra_dwords += 1; + else +@@ -289,7 +291,7 @@ void etnaviv_buffer_queue(struct etnaviv + + target = etnaviv_buffer_reserve(gpu, buffer, extra_dwords); + +- if (gpu->mmu->need_flush) { ++ if (need_flush) { + /* Add the MMU flush */ + if (gpu->mmu->version == ETNAVIV_IOMMU_V1) { + CMD_LOAD_STATE(buffer, VIVS_GL_FLUSH_MMU, +@@ -309,7 +311,7 @@ void etnaviv_buffer_queue(struct etnaviv + SYNC_RECIPIENT_PE); + } + +- gpu->mmu->need_flush = false; ++ gpu->flush_seq = new_flush_seq; + } + + if (gpu->switch_context) { +--- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c ++++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +@@ -1313,7 +1313,7 @@ int etnaviv_gpu_submit(struct etnaviv_gp + gpu->active_fence = submit->fence; + + if (gpu->lastctx != cmdbuf->ctx) { +- gpu->mmu->need_flush = true; ++ gpu->mmu->flush_seq++; + gpu->switch_context = true; + gpu->lastctx = cmdbuf->ctx; + } +--- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h ++++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h +@@ -135,6 +135,7 @@ struct etnaviv_gpu { + int irq; + + struct etnaviv_iommu *mmu; ++ unsigned int flush_seq; + + /* Power Control: */ + struct clk *clk_bus; +--- a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c ++++ b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c +@@ -134,7 +134,7 @@ static int etnaviv_iommu_find_iova(struc + */ + if (mmu->last_iova) { + mmu->last_iova = 0; +- mmu->need_flush = true; ++ mmu->flush_seq++; + continue; + } + +@@ -197,7 +197,7 @@ static int etnaviv_iommu_find_iova(struc + * associated commit requesting this mapping, and retry the + * allocation one more time. + */ +- mmu->need_flush = true; ++ mmu->flush_seq++; + } + + return ret; +@@ -354,7 +354,7 @@ u32 etnaviv_iommu_get_cmdbuf_va(struct e + * that the FE MMU prefetch won't load invalid entries. + */ + mmu->last_iova = buf->vram_node.start + buf->size + SZ_64K; +- gpu->mmu->need_flush = true; ++ mmu->flush_seq++; + mutex_unlock(&mmu->lock); + + return (u32)buf->vram_node.start; +--- a/drivers/gpu/drm/etnaviv/etnaviv_mmu.h ++++ b/drivers/gpu/drm/etnaviv/etnaviv_mmu.h +@@ -44,7 +44,7 @@ struct etnaviv_iommu { + struct list_head mappings; + struct drm_mm mm; + u32 last_iova; +- bool need_flush; ++ unsigned int flush_seq; + }; + + struct etnaviv_gem_object; diff --git a/queue-4.9/series b/queue-4.9/series index 1a094d501a9..3b93a345d37 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -5,3 +5,5 @@ ipv4-fix-a-rcu-list-lock-in-fib_triestat_seq_show.patch net-ip_tunnel-fix-interface-lookup-with-no-key.patch sctp-fix-refcount-bug-in-sctp_wfree.patch sctp-fix-possibly-using-a-bad-saddr-with-a-given-dst.patch +drm-etnaviv-replace-mmu-flush-marker-with-flush-sequence.patch +blk-mq-sync-the-update-nr_hw_queues-with-blk_mq_queue_tag_busy_iter.patch -- 2.47.3