msm_fence.c (2485B)
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#include <linux/dma-fence.h> 8 9#include "msm_drv.h" 10#include "msm_fence.h" 11 12 13struct msm_fence_context * 14msm_fence_context_alloc(struct drm_device *dev, volatile uint32_t *fenceptr, 15 const char *name) 16{ 17 struct msm_fence_context *fctx; 18 static int index = 0; 19 20 fctx = kzalloc(sizeof(*fctx), GFP_KERNEL); 21 if (!fctx) 22 return ERR_PTR(-ENOMEM); 23 24 fctx->dev = dev; 25 strncpy(fctx->name, name, sizeof(fctx->name)); 26 fctx->context = dma_fence_context_alloc(1); 27 fctx->index = index++; 28 fctx->fenceptr = fenceptr; 29 spin_lock_init(&fctx->spinlock); 30 31 return fctx; 32} 33 34void msm_fence_context_free(struct msm_fence_context *fctx) 35{ 36 kfree(fctx); 37} 38 39bool msm_fence_completed(struct msm_fence_context *fctx, uint32_t fence) 40{ 41 /* 42 * Note: Check completed_fence first, as fenceptr is in a write-combine 43 * mapping, so it will be more expensive to read. 44 */ 45 return (int32_t)(fctx->completed_fence - fence) >= 0 || 46 (int32_t)(*fctx->fenceptr - fence) >= 0; 47} 48 49/* called from irq handler and workqueue (in recover path) */ 50void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence) 51{ 52 unsigned long flags; 53 54 spin_lock_irqsave(&fctx->spinlock, flags); 55 fctx->completed_fence = max(fence, fctx->completed_fence); 56 spin_unlock_irqrestore(&fctx->spinlock, flags); 57} 58 59struct msm_fence { 60 struct dma_fence base; 61 struct msm_fence_context *fctx; 62}; 63 64static inline struct msm_fence *to_msm_fence(struct dma_fence *fence) 65{ 66 return container_of(fence, struct msm_fence, base); 67} 68 69static const char *msm_fence_get_driver_name(struct dma_fence *fence) 70{ 71 return "msm"; 72} 73 74static const char *msm_fence_get_timeline_name(struct dma_fence *fence) 75{ 76 struct msm_fence *f = to_msm_fence(fence); 77 return f->fctx->name; 78} 79 80static bool msm_fence_signaled(struct dma_fence *fence) 81{ 82 struct msm_fence *f = to_msm_fence(fence); 83 return msm_fence_completed(f->fctx, f->base.seqno); 84} 85 86static const struct dma_fence_ops msm_fence_ops = { 87 .get_driver_name = msm_fence_get_driver_name, 88 .get_timeline_name = msm_fence_get_timeline_name, 89 .signaled = msm_fence_signaled, 90}; 91 92struct dma_fence * 93msm_fence_alloc(struct msm_fence_context *fctx) 94{ 95 struct msm_fence *f; 96 97 f = kzalloc(sizeof(*f), GFP_KERNEL); 98 if (!f) 99 return ERR_PTR(-ENOMEM); 100 101 f->fctx = fctx; 102 103 dma_fence_init(&f->base, &msm_fence_ops, &fctx->spinlock, 104 fctx->context, ++fctx->last_fence); 105 106 return &f->base; 107}