drm/etnaviv: replace MMU flush marker with flush sequence
authorLucas Stach <l.stach@pengutronix.de>
Fri, 5 Jul 2019 17:17:23 +0000 (19:17 +0200)
committerLucas Stach <l.stach@pengutronix.de>
Thu, 15 Aug 2019 08:56:03 +0000 (10:56 +0200)
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 <l.stach@pengutronix.de>
Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>
Reviewed-by: Guido Günther <agx@sigxcpu.org>
drivers/gpu/drm/etnaviv/etnaviv_buffer.c
drivers/gpu/drm/etnaviv/etnaviv_gpu.h
drivers/gpu/drm/etnaviv/etnaviv_mmu.c
drivers/gpu/drm/etnaviv/etnaviv_mmu.h

index 6400a88..a3cdb20 100644 (file)
@@ -315,6 +315,8 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, u32 exec_state,
        u32 return_target, return_dwords;
        u32 link_target, link_dwords;
        bool switch_context = gpu->exec_state != exec_state;
+       unsigned int new_flush_seq = READ_ONCE(gpu->mmu->flush_seq);
+       bool need_flush = gpu->flush_seq != new_flush_seq;
 
        lockdep_assert_held(&gpu->lock);
 
@@ -329,14 +331,14 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, u32 exec_state,
         * 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 || switch_context) {
+       if (need_flush || 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
@@ -349,7 +351,7 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, u32 exec_state,
 
                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,
@@ -369,7 +371,7 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, u32 exec_state,
                                        SYNC_RECIPIENT_PE);
                        }
 
-                       gpu->mmu->need_flush = false;
+                       gpu->flush_seq = new_flush_seq;
                }
 
                if (switch_context) {
index 933c8d0..9638094 100644 (file)
@@ -137,6 +137,7 @@ struct etnaviv_gpu {
        int irq;
 
        struct etnaviv_iommu *mmu;
+       unsigned int flush_seq;
 
        /* Power Control: */
        struct clk *clk_bus;
index 09f5160..bbd1624 100644 (file)
@@ -263,7 +263,7 @@ int etnaviv_iommu_map_gem(struct etnaviv_iommu *mmu,
        }
 
        list_add_tail(&mapping->mmu_node, &mmu->mappings);
-       mmu->need_flush = true;
+       mmu->flush_seq++;
 unlock:
        mutex_unlock(&mmu->lock);
 
@@ -282,7 +282,7 @@ void etnaviv_iommu_unmap_gem(struct etnaviv_iommu *mmu,
                etnaviv_iommu_remove_mapping(mmu, mapping);
 
        list_del(&mapping->mmu_node);
-       mmu->need_flush = true;
+       mmu->flush_seq++;
        mutex_unlock(&mmu->lock);
 }
 
@@ -369,7 +369,7 @@ int etnaviv_iommu_get_suballoc_va(struct etnaviv_iommu *mmu,
                        return ret;
                }
 
-               mmu->need_flush = true;
+               mmu->flush_seq++;
        }
 
        list_add_tail(&mapping->mmu_node, &mmu->mappings);
index fe1c9d6..34afe25 100644 (file)
@@ -48,7 +48,7 @@ struct etnaviv_iommu {
        struct mutex lock;
        struct list_head mappings;
        struct drm_mm mm;
-       bool need_flush;
+       unsigned int flush_seq;
 };
 
 struct etnaviv_gem_object;