1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * Copyright (C) 2013-2016 Red Hat 4 * Author: Rob Clark <robdclark@gmail.com> 5 */ 6 7 #ifndef __MSM_FENCE_H__ 8 #define __MSM_FENCE_H__ 9 10 #include "msm_drv.h" 11 12 /** 13 * struct msm_fence_context - fence context for gpu 14 * 15 * Each ringbuffer has a single fence context, with the GPU writing an 16 * incrementing fence seqno at the end of each submit 17 */ 18 struct msm_fence_context { 19 struct drm_device *dev; 20 /** name: human readable name for fence timeline */ 21 char name[32]; 22 /** context: see dma_fence_context_alloc() */ 23 unsigned context; 24 /** index: similar to context, but local to msm_fence_context's */ 25 unsigned index; 26 27 /** 28 * last_fence: 29 * 30 * Last assigned fence, incremented each time a fence is created 31 * on this fence context. If last_fence == completed_fence, 32 * there is no remaining pending work 33 */ 34 uint32_t last_fence; 35 36 /** 37 * completed_fence: 38 * 39 * The last completed fence, updated from the CPU after interrupt 40 * from GPU 41 */ 42 uint32_t completed_fence; 43 44 /** 45 * fenceptr: 46 * 47 * The address that the GPU directly writes with completed fence 48 * seqno. This can be ahead of completed_fence. We can peek at 49 * this to see if a fence has already signaled but the CPU hasn't 50 * gotten around to handling the irq and updating completed_fence 51 */ 52 volatile uint32_t *fenceptr; 53 54 spinlock_t spinlock; 55 56 /* 57 * TODO this doesn't really deal with multiple deadlines, like 58 * if userspace got multiple frames ahead.. OTOH atomic updates 59 * don't queue, so maybe that is ok 60 */ 61 62 /** next_deadline: Time of next deadline */ 63 ktime_t next_deadline; 64 65 /** 66 * next_deadline_fence: 67 * 68 * Fence value for next pending deadline. The deadline timer is 69 * canceled when this fence is signaled. 70 */ 71 uint32_t next_deadline_fence; 72 73 struct hrtimer deadline_timer; 74 struct kthread_work deadline_work; 75 }; 76 77 struct msm_fence_context * msm_fence_context_alloc(struct drm_device *dev, 78 volatile uint32_t *fenceptr, const char *name); 79 void msm_fence_context_free(struct msm_fence_context *fctx); 80 81 bool msm_fence_completed(struct msm_fence_context *fctx, uint32_t fence); 82 void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence); 83 84 struct dma_fence * msm_fence_alloc(void); 85 void msm_fence_init(struct dma_fence *fence, struct msm_fence_context *fctx); 86 87 static inline bool 88 fence_before(uint32_t a, uint32_t b) 89 { 90 return (int32_t)(a - b) < 0; 91 } 92 93 static inline bool 94 fence_after(uint32_t a, uint32_t b) 95 { 96 return (int32_t)(a - b) > 0; 97 } 98 99 #endif 100