0001
0002
0003
0004
0005
0006
0007 #include <linux/dma-fence.h>
0008
0009 #include "msm_drv.h"
0010 #include "msm_fence.h"
0011
0012
0013 struct msm_fence_context *
0014 msm_fence_context_alloc(struct drm_device *dev, volatile uint32_t *fenceptr,
0015 const char *name)
0016 {
0017 struct msm_fence_context *fctx;
0018 static int index = 0;
0019
0020 fctx = kzalloc(sizeof(*fctx), GFP_KERNEL);
0021 if (!fctx)
0022 return ERR_PTR(-ENOMEM);
0023
0024 fctx->dev = dev;
0025 strncpy(fctx->name, name, sizeof(fctx->name));
0026 fctx->context = dma_fence_context_alloc(1);
0027 fctx->index = index++;
0028 fctx->fenceptr = fenceptr;
0029 spin_lock_init(&fctx->spinlock);
0030
0031
0032
0033
0034
0035 fctx->last_fence = 0xffffff00;
0036 fctx->completed_fence = fctx->last_fence;
0037 *fctx->fenceptr = fctx->last_fence;
0038
0039 return fctx;
0040 }
0041
0042 void msm_fence_context_free(struct msm_fence_context *fctx)
0043 {
0044 kfree(fctx);
0045 }
0046
0047 bool msm_fence_completed(struct msm_fence_context *fctx, uint32_t fence)
0048 {
0049
0050
0051
0052
0053 return (int32_t)(fctx->completed_fence - fence) >= 0 ||
0054 (int32_t)(*fctx->fenceptr - fence) >= 0;
0055 }
0056
0057
0058 void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence)
0059 {
0060 unsigned long flags;
0061
0062 spin_lock_irqsave(&fctx->spinlock, flags);
0063 if (fence_after(fence, fctx->completed_fence))
0064 fctx->completed_fence = fence;
0065 spin_unlock_irqrestore(&fctx->spinlock, flags);
0066 }
0067
0068 struct msm_fence {
0069 struct dma_fence base;
0070 struct msm_fence_context *fctx;
0071 };
0072
0073 static inline struct msm_fence *to_msm_fence(struct dma_fence *fence)
0074 {
0075 return container_of(fence, struct msm_fence, base);
0076 }
0077
0078 static const char *msm_fence_get_driver_name(struct dma_fence *fence)
0079 {
0080 return "msm";
0081 }
0082
0083 static const char *msm_fence_get_timeline_name(struct dma_fence *fence)
0084 {
0085 struct msm_fence *f = to_msm_fence(fence);
0086 return f->fctx->name;
0087 }
0088
0089 static bool msm_fence_signaled(struct dma_fence *fence)
0090 {
0091 struct msm_fence *f = to_msm_fence(fence);
0092 return msm_fence_completed(f->fctx, f->base.seqno);
0093 }
0094
0095 static const struct dma_fence_ops msm_fence_ops = {
0096 .get_driver_name = msm_fence_get_driver_name,
0097 .get_timeline_name = msm_fence_get_timeline_name,
0098 .signaled = msm_fence_signaled,
0099 };
0100
0101 struct dma_fence *
0102 msm_fence_alloc(struct msm_fence_context *fctx)
0103 {
0104 struct msm_fence *f;
0105
0106 f = kzalloc(sizeof(*f), GFP_KERNEL);
0107 if (!f)
0108 return ERR_PTR(-ENOMEM);
0109
0110 f->fctx = fctx;
0111
0112 dma_fence_init(&f->base, &msm_fence_ops, &fctx->spinlock,
0113 fctx->context, ++fctx->last_fence);
0114
0115 return &f->base;
0116 }