mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
103 lines
2.3 KiB
103 lines
2.3 KiB
// SPDX-License-Identifier: GPL-2.0-only |
|
/* |
|
* Copyright (C) 2013-2016 Red Hat |
|
* Author: Rob Clark <[email protected]> |
|
*/ |
|
|
|
#include <linux/dma-fence.h> |
|
|
|
#include "msm_drv.h" |
|
#include "msm_fence.h" |
|
|
|
|
|
struct msm_fence_context * |
|
msm_fence_context_alloc(struct drm_device *dev, volatile uint32_t *fenceptr, |
|
const char *name) |
|
{ |
|
struct msm_fence_context *fctx; |
|
|
|
fctx = kzalloc(sizeof(*fctx), GFP_KERNEL); |
|
if (!fctx) |
|
return ERR_PTR(-ENOMEM); |
|
|
|
fctx->dev = dev; |
|
strncpy(fctx->name, name, sizeof(fctx->name)); |
|
fctx->context = dma_fence_context_alloc(1); |
|
fctx->fenceptr = fenceptr; |
|
spin_lock_init(&fctx->spinlock); |
|
|
|
return fctx; |
|
} |
|
|
|
void msm_fence_context_free(struct msm_fence_context *fctx) |
|
{ |
|
kfree(fctx); |
|
} |
|
|
|
static inline bool fence_completed(struct msm_fence_context *fctx, uint32_t fence) |
|
{ |
|
/* |
|
* Note: Check completed_fence first, as fenceptr is in a write-combine |
|
* mapping, so it will be more expensive to read. |
|
*/ |
|
return (int32_t)(fctx->completed_fence - fence) >= 0 || |
|
(int32_t)(*fctx->fenceptr - fence) >= 0; |
|
} |
|
|
|
/* called from workqueue */ |
|
void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence) |
|
{ |
|
spin_lock(&fctx->spinlock); |
|
fctx->completed_fence = max(fence, fctx->completed_fence); |
|
spin_unlock(&fctx->spinlock); |
|
} |
|
|
|
struct msm_fence { |
|
struct dma_fence base; |
|
struct msm_fence_context *fctx; |
|
}; |
|
|
|
static inline struct msm_fence *to_msm_fence(struct dma_fence *fence) |
|
{ |
|
return container_of(fence, struct msm_fence, base); |
|
} |
|
|
|
static const char *msm_fence_get_driver_name(struct dma_fence *fence) |
|
{ |
|
return "msm"; |
|
} |
|
|
|
static const char *msm_fence_get_timeline_name(struct dma_fence *fence) |
|
{ |
|
struct msm_fence *f = to_msm_fence(fence); |
|
return f->fctx->name; |
|
} |
|
|
|
static bool msm_fence_signaled(struct dma_fence *fence) |
|
{ |
|
struct msm_fence *f = to_msm_fence(fence); |
|
return fence_completed(f->fctx, f->base.seqno); |
|
} |
|
|
|
static const struct dma_fence_ops msm_fence_ops = { |
|
.get_driver_name = msm_fence_get_driver_name, |
|
.get_timeline_name = msm_fence_get_timeline_name, |
|
.signaled = msm_fence_signaled, |
|
}; |
|
|
|
struct dma_fence * |
|
msm_fence_alloc(struct msm_fence_context *fctx) |
|
{ |
|
struct msm_fence *f; |
|
|
|
f = kzalloc(sizeof(*f), GFP_KERNEL); |
|
if (!f) |
|
return ERR_PTR(-ENOMEM); |
|
|
|
f->fctx = fctx; |
|
|
|
dma_fence_init(&f->base, &msm_fence_ops, &fctx->spinlock, |
|
fctx->context, ++fctx->last_fence); |
|
|
|
return &f->base; |
|
}
|
|
|