diff options
Diffstat (limited to 'include/linux/dma-fence.h')
| -rw-r--r-- | include/linux/dma-fence.h | 111 |
1 files changed, 75 insertions, 36 deletions
diff --git a/include/linux/dma-fence.h b/include/linux/dma-fence.h index 0d678e9a7b24..64639e104110 100644 --- a/include/linux/dma-fence.h +++ b/include/linux/dma-fence.h @@ -21,10 +21,12 @@ #include <linux/sched.h> #include <linux/printk.h> #include <linux/rcupdate.h> +#include <linux/timekeeping.h> struct dma_fence; struct dma_fence_ops; struct dma_fence_cb; +struct seq_file; /** * struct dma_fence - software synchronization primitive @@ -96,6 +98,7 @@ struct dma_fence { }; enum dma_fence_flag_bits { + DMA_FENCE_FLAG_SEQNO64_BIT, DMA_FENCE_FLAG_SIGNALED_BIT, DMA_FENCE_FLAG_TIMESTAMP_BIT, DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, @@ -124,14 +127,6 @@ struct dma_fence_cb { */ struct dma_fence_ops { /** - * @use_64bit_seqno: - * - * True if this dma_fence implementation uses 64bit seqno, false - * otherwise. - */ - bool use_64bit_seqno; - - /** * @get_driver_name: * * Returns the driver name. This is a callback to allow drivers to @@ -168,8 +163,8 @@ struct dma_fence_ops { * implementation know that there is another driver waiting on the * signal (ie. hw->sw case). * - * This function can be called from atomic context, but not - * from irq context, so normal spinlocks can be used. + * This is called with irq's disabled, so only spinlocks which disable + * IRQ's can be used in the code outside of this callback. * * A return value of false indicates the fence already passed, * or some failure occurred that made it impossible to enable @@ -238,27 +233,6 @@ struct dma_fence_ops { void (*release)(struct dma_fence *fence); /** - * @fence_value_str: - * - * Callback to fill in free-form debug info specific to this fence, like - * the sequence number. - * - * This callback is optional. - */ - void (*fence_value_str)(struct dma_fence *fence, char *str, int size); - - /** - * @timeline_value_str: - * - * Fills in the current value of the timeline as a string, like the - * sequence number. Note that the specific fence passed to this function - * should not matter, drivers should only use it to look up the - * corresponding timeline structures. - */ - void (*timeline_value_str)(struct dma_fence *fence, - char *str, int size); - - /** * @set_deadline: * * Callback to allow a fence waiter to inform the fence signaler of @@ -282,6 +256,9 @@ struct dma_fence_ops { void dma_fence_init(struct dma_fence *fence, const struct dma_fence_ops *ops, spinlock_t *lock, u64 context, u64 seqno); +void dma_fence_init64(struct dma_fence *fence, const struct dma_fence_ops *ops, + spinlock_t *lock, u64 context, u64 seqno); + void dma_fence_release(struct kref *kref); void dma_fence_free(struct dma_fence *fence); void dma_fence_describe(struct dma_fence *fence, struct seq_file *seq); @@ -402,6 +379,29 @@ bool dma_fence_remove_callback(struct dma_fence *fence, void dma_fence_enable_sw_signaling(struct dma_fence *fence); /** + * DOC: Safe external access to driver provided object members + * + * All data not stored directly in the dma-fence object, such as the + * &dma_fence.lock and memory potentially accessed by functions in the + * &dma_fence.ops table, MUST NOT be accessed after the fence has been signalled + * because after that point drivers are allowed to free it. + * + * All code accessing that data via the dma-fence API (or directly, which is + * discouraged), MUST make sure to contain the complete access within a + * &rcu_read_lock and &rcu_read_unlock pair. + * + * Some dma-fence API handles this automatically, while other, as for example + * &dma_fence_driver_name and &dma_fence_timeline_name, leave that + * responsibility to the caller. + * + * To enable this scheme to work drivers MUST ensure a RCU grace period elapses + * between signalling the fence and freeing the said data. + * + */ +const char __rcu *dma_fence_driver_name(struct dma_fence *fence); +const char __rcu *dma_fence_timeline_name(struct dma_fence *fence); + +/** * dma_fence_is_signaled_locked - Return an indication if the fence * is signaled yet. * @fence: the fence to check @@ -461,21 +461,20 @@ dma_fence_is_signaled(struct dma_fence *fence) /** * __dma_fence_is_later - return if f1 is chronologically later than f2 + * @fence: fence in whose context to do the comparison * @f1: the first fence's seqno * @f2: the second fence's seqno from the same context - * @ops: dma_fence_ops associated with the seqno * * Returns true if f1 is chronologically later than f2. Both fences must be * from the same context, since a seqno is not common across contexts. */ -static inline bool __dma_fence_is_later(u64 f1, u64 f2, - const struct dma_fence_ops *ops) +static inline bool __dma_fence_is_later(struct dma_fence *fence, u64 f1, u64 f2) { /* This is for backward compatibility with drivers which can only handle * 32bit sequence numbers. Use a 64bit compare when the driver says to * do so. */ - if (ops->use_64bit_seqno) + if (test_bit(DMA_FENCE_FLAG_SEQNO64_BIT, &fence->flags)) return f1 > f2; return (int)(lower_32_bits(f1) - lower_32_bits(f2)) > 0; @@ -495,7 +494,22 @@ static inline bool dma_fence_is_later(struct dma_fence *f1, if (WARN_ON(f1->context != f2->context)) return false; - return __dma_fence_is_later(f1->seqno, f2->seqno, f1->ops); + return __dma_fence_is_later(f1, f1->seqno, f2->seqno); +} + +/** + * dma_fence_is_later_or_same - return true if f1 is later or same as f2 + * @f1: the first fence from the same context + * @f2: the second fence from the same context + * + * Returns true if f1 is chronologically later than f2 or the same fence. Both + * fences must be from the same context, since a seqno is not re-used across + * contexts. + */ +static inline bool dma_fence_is_later_or_same(struct dma_fence *f1, + struct dma_fence *f2) +{ + return f1 == f2 || dma_fence_is_later(f1, f2); } /** @@ -558,6 +572,12 @@ int dma_fence_get_status(struct dma_fence *fence); * rather than success. This must be set before signaling (so that the value * is visible before any waiters on the signal callback are woken). This * helper exists to help catching erroneous setting of #dma_fence.error. + * + * Examples of error codes which drivers should use: + * + * * %-ENODATA This operation produced no data, no other operation affected. + * * %-ECANCELED All operations from the same context have been canceled. + * * %-ETIME Operation caused a timeout and potentially device reset. */ static inline void dma_fence_set_error(struct dma_fence *fence, int error) @@ -568,6 +588,25 @@ static inline void dma_fence_set_error(struct dma_fence *fence, fence->error = error; } +/** + * dma_fence_timestamp - helper to get the completion timestamp of a fence + * @fence: fence to get the timestamp from. + * + * After a fence is signaled the timestamp is updated with the signaling time, + * but setting the timestamp can race with tasks waiting for the signaling. This + * helper busy waits for the correct timestamp to appear. + */ +static inline ktime_t dma_fence_timestamp(struct dma_fence *fence) +{ + if (WARN_ON(!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))) + return ktime_get(); + + while (!test_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT, &fence->flags)) + cpu_relax(); + + return fence->timestamp; +} + signed long dma_fence_wait_timeout(struct dma_fence *, bool intr, signed long timeout); signed long dma_fence_wait_any_timeout(struct dma_fence **fences, |
