summaryrefslogtreecommitdiff
path: root/drivers/dma-buf/dma-fence-chain.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/dma-buf/dma-fence-chain.c')
-rw-r--r--drivers/dma-buf/dma-fence-chain.c48
1 files changed, 30 insertions, 18 deletions
diff --git a/drivers/dma-buf/dma-fence-chain.c b/drivers/dma-buf/dma-fence-chain.c
index c435bbba851c..a8a90acf4f34 100644
--- a/drivers/dma-buf/dma-fence-chain.c
+++ b/drivers/dma-buf/dma-fence-chain.c
@@ -62,8 +62,8 @@ struct dma_fence *dma_fence_chain_walk(struct dma_fence *fence)
replacement = NULL;
}
- tmp = cmpxchg((struct dma_fence __force **)&chain->prev,
- prev, replacement);
+ tmp = unrcu_pointer(cmpxchg(&chain->prev, RCU_INITIALIZER(prev),
+ RCU_INITIALIZER(replacement)));
if (tmp == prev)
dma_fence_put(tmp);
else
@@ -99,12 +99,6 @@ int dma_fence_chain_find_seqno(struct dma_fence **pfence, uint64_t seqno)
return -EINVAL;
dma_fence_chain_for_each(*pfence, &chain->base) {
- if ((*pfence)->seqno < seqno) { /* already signaled */
- dma_fence_put(*pfence);
- *pfence = NULL;
- break;
- }
-
if ((*pfence)->context != chain->base.context ||
to_dma_fence_chain(*pfence)->prev_seqno < seqno)
break;
@@ -143,6 +137,7 @@ static void dma_fence_chain_cb(struct dma_fence *f, struct dma_fence_cb *cb)
struct dma_fence_chain *chain;
chain = container_of(cb, typeof(*chain), cb);
+ init_irq_work(&chain->work, dma_fence_chain_irq_work);
irq_work_queue(&chain->work);
dma_fence_put(f);
}
@@ -153,8 +148,7 @@ static bool dma_fence_chain_enable_signaling(struct dma_fence *fence)
dma_fence_get(&head->base);
dma_fence_chain_for_each(fence, &head->base) {
- struct dma_fence_chain *chain = to_dma_fence_chain(fence);
- struct dma_fence *f = chain ? chain->fence : fence;
+ struct dma_fence *f = dma_fence_chain_contained(fence);
dma_fence_get(f);
if (!dma_fence_add_callback(f, &head->cb, dma_fence_chain_cb)) {
@@ -170,8 +164,7 @@ static bool dma_fence_chain_enable_signaling(struct dma_fence *fence)
static bool dma_fence_chain_signaled(struct dma_fence *fence)
{
dma_fence_chain_for_each(fence, fence) {
- struct dma_fence_chain *chain = to_dma_fence_chain(fence);
- struct dma_fence *f = chain ? chain->fence : fence;
+ struct dma_fence *f = dma_fence_chain_contained(fence);
if (!dma_fence_is_signaled(f)) {
dma_fence_put(fence);
@@ -213,13 +206,24 @@ static void dma_fence_chain_release(struct dma_fence *fence)
dma_fence_free(fence);
}
+
+static void dma_fence_chain_set_deadline(struct dma_fence *fence,
+ ktime_t deadline)
+{
+ dma_fence_chain_for_each(fence, fence) {
+ struct dma_fence *f = dma_fence_chain_contained(fence);
+
+ dma_fence_set_deadline(f, deadline);
+ }
+}
+
const struct dma_fence_ops dma_fence_chain_ops = {
- .use_64bit_seqno = true,
.get_driver_name = dma_fence_chain_get_driver_name,
.get_timeline_name = dma_fence_chain_get_timeline_name,
.enable_signaling = dma_fence_chain_enable_signaling,
.signaled = dma_fence_chain_signaled,
.release = dma_fence_chain_release,
+ .set_deadline = dma_fence_chain_set_deadline,
};
EXPORT_SYMBOL(dma_fence_chain_ops);
@@ -228,7 +232,7 @@ EXPORT_SYMBOL(dma_fence_chain_ops);
* @chain: the chain node to initialize
* @prev: the previous fence
* @fence: the current fence
- * @seqno: the sequence number (syncpt) of the fence within the chain
+ * @seqno: the sequence number to use for the fence chain
*
* Initialize a new chain node and either start a new chain or add the node to
* the existing chain of the previous fence.
@@ -245,10 +249,9 @@ void dma_fence_chain_init(struct dma_fence_chain *chain,
rcu_assign_pointer(chain->prev, prev);
chain->fence = fence;
chain->prev_seqno = 0;
- init_irq_work(&chain->work, dma_fence_chain_irq_work);
/* Try to reuse the context of the previous chain node. */
- if (prev_chain && __dma_fence_is_later(seqno, prev->seqno, prev->ops)) {
+ if (prev_chain && __dma_fence_is_later(prev, seqno, prev->seqno)) {
context = prev->context;
chain->prev_seqno = prev->seqno;
} else {
@@ -258,7 +261,16 @@ void dma_fence_chain_init(struct dma_fence_chain *chain,
seqno = max(prev->seqno, seqno);
}
- dma_fence_init(&chain->base, &dma_fence_chain_ops,
- &chain->lock, context, seqno);
+ dma_fence_init64(&chain->base, &dma_fence_chain_ops, &chain->lock,
+ context, seqno);
+
+ /*
+ * Chaining dma_fence_chain container together is only allowed through
+ * the prev fence and not through the contained fence.
+ *
+ * The correct way of handling this is to flatten out the fence
+ * structure into a dma_fence_array by the caller instead.
+ */
+ WARN_ON(dma_fence_is_chain(fence));
}
EXPORT_SYMBOL(dma_fence_chain_init);