dma-buf/fence: make fence context 64 bit v2
authorChristian König <christian.koenig@amd.com>
Wed, 1 Jun 2016 13:10:02 +0000 (15:10 +0200)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Thu, 2 Jun 2016 06:27:41 +0000 (08:27 +0200)
Fence contexts are created on the fly (for example) by the GPU scheduler used
in the amdgpu driver as a result of an userspace request. Because of this
userspace could in theory force a wrap around of the 32bit context number
if it doesn't behave well.

Avoid this by increasing the context number to 64bits. This way even when
userspace manages to allocate a billion contexts per second it takes more
than 500 years for the context number to wrap around.

v2: fix printf formats as well.

Signed-off-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
Acked-by: Sumit Semwal <sumit.semwal@linaro.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: http://patchwork.freedesktop.org/patch/msgid/1464786612-5010-2-git-send-email-deathsimple@vodafone.de
drivers/dma-buf/fence.c
drivers/gpu/drm/amd/amdgpu/amdgpu.h
drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c
drivers/gpu/drm/etnaviv/etnaviv_gpu.h
drivers/gpu/drm/nouveau/nouveau_fence.h
drivers/gpu/drm/qxl/qxl_release.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
drivers/staging/android/sync.h
include/linux/fence.h

index 7b05dbe9b2964fd8c431dde0512a0ba2f4fd6ff2..4d51f9e83fa83ad9a815cb8525756437d81fe650 100644 (file)
@@ -35,7 +35,7 @@ EXPORT_TRACEPOINT_SYMBOL(fence_emit);
  * context or not. One device can have multiple separate contexts,
  * and they're used if some engine can run independently of another.
  */
-static atomic_t fence_context_counter = ATOMIC_INIT(0);
+static atomic64_t fence_context_counter = ATOMIC64_INIT(0);
 
 /**
  * fence_context_alloc - allocate an array of fence contexts
@@ -44,10 +44,10 @@ static atomic_t fence_context_counter = ATOMIC_INIT(0);
  * This function will return the first index of the number of fences allocated.
  * The fence context is used for setting fence->context to a unique number.
  */
-unsigned fence_context_alloc(unsigned num)
+u64 fence_context_alloc(unsigned num)
 {
        BUG_ON(!num);
-       return atomic_add_return(num, &fence_context_counter) - num;
+       return atomic64_add_return(num, &fence_context_counter) - num;
 }
 EXPORT_SYMBOL(fence_context_alloc);
 
@@ -513,7 +513,7 @@ EXPORT_SYMBOL(fence_wait_any_timeout);
  */
 void
 fence_init(struct fence *fence, const struct fence_ops *ops,
-            spinlock_t *lock, unsigned context, unsigned seqno)
+            spinlock_t *lock, u64 context, unsigned seqno)
 {
        BUG_ON(!lock);
        BUG_ON(!ops || !ops->wait || !ops->enable_signaling ||
index 992f00b65be45a2b9ca8f16058aaed076918ae2e..da3d02154fa622a09897d9d5d505befae949c9ee 100644 (file)
@@ -2032,7 +2032,7 @@ struct amdgpu_device {
        struct amdgpu_irq_src           hpd_irq;
 
        /* rings */
-       unsigned                        fence_context;
+       u64                             fence_context;
        unsigned                        num_rings;
        struct amdgpu_ring              *rings[AMDGPU_MAX_RINGS];
        bool                            ib_pool_ready;
index 8bf84efafb049cd693e156a8dbf2dff396c70164..b16366c2b4a0863ce0b40994c62cbc45ba779c7b 100644 (file)
@@ -427,7 +427,7 @@ void amdgpu_sa_bo_dump_debug_info(struct amdgpu_sa_manager *sa_manager,
                           soffset, eoffset, eoffset - soffset);
 
                if (i->fence)
-                       seq_printf(m, " protected by 0x%08x on context %d",
+                       seq_printf(m, " protected by 0x%08x on context %llu",
                                   i->fence->seqno, i->fence->context);
 
                seq_printf(m, "\n");
index f5321e2f25ffd293caa19a6fca32672adfe9a939..a69cdd526bf83149af1ee486c34d96a6e1913123 100644 (file)
@@ -125,7 +125,7 @@ struct etnaviv_gpu {
        u32 completed_fence;
        u32 retired_fence;
        wait_queue_head_t fence_event;
-       unsigned int fence_context;
+       u64 fence_context;
        spinlock_t fence_spinlock;
 
        /* worker for handling active-list retiring: */
index 2e3a62d38fe9d48503daf8d1450c5fcf256f1e02..64c4ce7115ad8902d9b79714d8a476d12d1e71c3 100644 (file)
@@ -57,7 +57,8 @@ struct nouveau_fence_priv {
        int  (*context_new)(struct nouveau_channel *);
        void (*context_del)(struct nouveau_channel *);
 
-       u32 contexts, context_base;
+       u32 contexts;
+       u64 context_base;
        bool uevent;
 };
 
index 4efa8e261baf59546ca24eb39920bc4159358ab7..f599cd073b722cd4c9db4c2634582dbe901120d3 100644 (file)
@@ -96,7 +96,7 @@ retry:
                        return 0;
 
                if (have_drawable_releases && sc > 300) {
-                       FENCE_WARN(fence, "failed to wait on release %d "
+                       FENCE_WARN(fence, "failed to wait on release %llu "
                                          "after spincount %d\n",
                                          fence->context & ~0xf0000000, sc);
                        goto signaled;
index 80b24a495d6c5805e7e12ed309b7008a77f536d5..5633ee3eb46e7d3d9a7197b2c5c909db326ba03b 100644 (file)
@@ -2386,7 +2386,7 @@ struct radeon_device {
        struct radeon_mman              mman;
        struct radeon_fence_driver      fence_drv[RADEON_NUM_RINGS];
        wait_queue_head_t               fence_queue;
-       unsigned                        fence_context;
+       u64                             fence_context;
        struct mutex                    ring_lock;
        struct radeon_ring              ring[RADEON_NUM_RINGS];
        bool                            ib_pool_ready;
index e959df6ede83e0a7b3b72e3c16df313f4df98940..26ac8e80a4786a674f52fb72792b4d6160416b27 100644 (file)
@@ -46,7 +46,7 @@ struct vmw_fence_manager {
        bool goal_irq_on; /* Protected by @goal_irq_mutex */
        bool seqno_valid; /* Protected by @lock, and may not be set to true
                             without the @goal_irq_mutex held. */
-       unsigned ctx;
+       u64 ctx;
 };
 
 struct vmw_user_fence {
index b56885c148396a845e62464d38aed2d6832f6625..ebb34dca60dfef38e1924531245596881e4f2760 100644 (file)
@@ -68,7 +68,8 @@ struct sync_timeline {
 
        /* protected by child_list_lock */
        bool                    destroyed;
-       int                     context, value;
+       u64                     context;
+       int                     value;
 
        struct list_head        child_list_head;
        spinlock_t              child_list_lock;
index 2b17698b60b844a6c08b490f506ec87033d89fc5..18a97c6b79dbda890b5b5c95d277311f1c7e996b 100644 (file)
@@ -75,7 +75,8 @@ struct fence {
        struct rcu_head rcu;
        struct list_head cb_list;
        spinlock_t *lock;
-       unsigned context, seqno;
+       u64 context;
+       unsigned seqno;
        unsigned long flags;
        ktime_t timestamp;
        int status;
@@ -178,7 +179,7 @@ struct fence_ops {
 };
 
 void fence_init(struct fence *fence, const struct fence_ops *ops,
-               spinlock_t *lock, unsigned context, unsigned seqno);
+               spinlock_t *lock, u64 context, unsigned seqno);
 
 void fence_release(struct kref *kref);
 void fence_free(struct fence *fence);
@@ -352,27 +353,27 @@ static inline signed long fence_wait(struct fence *fence, bool intr)
        return ret < 0 ? ret : 0;
 }
 
-unsigned fence_context_alloc(unsigned num);
+u64 fence_context_alloc(unsigned num);
 
 #define FENCE_TRACE(f, fmt, args...) \
        do {                                                            \
                struct fence *__ff = (f);                               \
                if (config_enabled(CONFIG_FENCE_TRACE))                 \
-                       pr_info("f %u#%u: " fmt,                        \
+                       pr_info("f %llu#%u: " fmt,                      \
                                __ff->context, __ff->seqno, ##args);    \
        } while (0)
 
 #define FENCE_WARN(f, fmt, args...) \
        do {                                                            \
                struct fence *__ff = (f);                               \
-               pr_warn("f %u#%u: " fmt, __ff->context, __ff->seqno,    \
+               pr_warn("f %llu#%u: " fmt, __ff->context, __ff->seqno,  \
                         ##args);                                       \
        } while (0)
 
 #define FENCE_ERR(f, fmt, args...) \
        do {                                                            \
                struct fence *__ff = (f);                               \
-               pr_err("f %u#%u: " fmt, __ff->context, __ff->seqno,     \
+               pr_err("f %llu#%u: " fmt, __ff->context, __ff->seqno,   \
                        ##args);                                        \
        } while (0)