.get_timeline_name = dma_fence_array_get_timeline_name,
.enable_signaling = dma_fence_array_enable_signaling,
.signaled = dma_fence_array_signaled,
+ .wait = dma_fence_default_wait,
.release = dma_fence_array_release,
};
EXPORT_SYMBOL(dma_fence_array_ops);
return -EINVAL;
trace_dma_fence_wait_start(fence);
- if (fence->ops->wait)
- ret = fence->ops->wait(fence, intr, timeout);
- else
- ret = dma_fence_default_wait(fence, intr, timeout);
+ ret = fence->ops->wait(fence, intr, timeout);
trace_dma_fence_wait_end(fence);
return ret;
}
}
EXPORT_SYMBOL(dma_fence_release);
-/**
- * dma_fence_free - default release function for &dma_fence.
- * @fence: fence to release
- *
- * This is the default implementation for &dma_fence_ops.release. It calls
- * kfree_rcu() on @fence.
- */
void dma_fence_free(struct dma_fence *fence)
{
kfree_rcu(fence, rcu);
for (i = 0; i < count; ++i) {
struct dma_fence *fence = fences[i];
+ if (fence->ops->wait != dma_fence_default_wait) {
+ ret = -EINVAL;
+ goto fence_rm_cb;
+ }
+
cb[i].task = current;
if (dma_fence_add_callback(fence, &cb[i].base,
dma_fence_default_wait_cb)) {
spinlock_t *lock, u64 context, unsigned seqno)
{
BUG_ON(!lock);
- BUG_ON(!ops || !ops->wait ||
+ BUG_ON(!ops || !ops->wait || !ops->enable_signaling ||
!ops->get_driver_name || !ops->get_timeline_name);
kref_init(&fence->refcount);
fence->flags = 0UL;
fence->error = 0;
- if (!ops->enable_signaling)
- set_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT,
- &fence->flags);
-
trace_dma_fence_init(fence);
}
EXPORT_SYMBOL(dma_fence_init);
.get_timeline_name = timeline_fence_get_timeline_name,
.enable_signaling = timeline_fence_enable_signaling,
.signaled = timeline_fence_signaled,
+ .wait = dma_fence_default_wait,
.release = timeline_fence_release,
.fence_value_str = timeline_fence_value_str,
.timeline_value_str = timeline_fence_timeline_value_str,
return crtc->timeline_name;
}
+static bool drm_crtc_fence_enable_signaling(struct dma_fence *fence)
+{
+ return true;
+}
+
static const struct dma_fence_ops drm_crtc_fence_ops = {
.get_driver_name = drm_crtc_fence_get_driver_name,
.get_timeline_name = drm_crtc_fence_get_timeline_name,
+ .enable_signaling = drm_crtc_fence_enable_signaling,
+ .wait = dma_fence_default_wait,
};
struct dma_fence *drm_crtc_create_fence(struct drm_crtc *crtc)
.get_driver_name = drm_syncobj_null_fence_get_name,
.get_timeline_name = drm_syncobj_null_fence_get_name,
.enable_signaling = drm_syncobj_null_fence_enable_signaling,
+ .wait = dma_fence_default_wait,
.release = NULL,
};
return "release";
}
+static bool qxl_nop_signaling(struct dma_fence *fence)
+{
+ /* fences are always automatically signaled, so just pretend we did this.. */
+ return true;
+}
+
static long qxl_fence_wait(struct dma_fence *fence, bool intr,
signed long timeout)
{
static const struct dma_fence_ops qxl_fence_ops = {
.get_driver_name = qxl_get_driver_name,
.get_timeline_name = qxl_get_timeline_name,
+ .enable_signaling = qxl_nop_signaling,
.wait = qxl_fence_wait,
};
return (const char *)fence->sched->name;
}
+static bool drm_sched_fence_enable_signaling(struct dma_fence *f)
+{
+ return true;
+}
+
/**
* amd_sched_fence_free - free up the fence memory
*
const struct dma_fence_ops drm_sched_fence_ops_scheduled = {
.get_driver_name = drm_sched_fence_get_driver_name,
.get_timeline_name = drm_sched_fence_get_timeline_name,
+ .enable_signaling = drm_sched_fence_enable_signaling,
+ .signaled = NULL,
+ .wait = dma_fence_default_wait,
.release = drm_sched_fence_release_scheduled,
};
const struct dma_fence_ops drm_sched_fence_ops_finished = {
.get_driver_name = drm_sched_fence_get_driver_name,
.get_timeline_name = drm_sched_fence_get_timeline_name,
+ .enable_signaling = drm_sched_fence_enable_signaling,
+ .signaled = NULL,
+ .wait = dma_fence_default_wait,
.release = drm_sched_fence_release_finished,
};
* released when the fence is signalled (through e.g. the interrupt
* handler).
*
- * This callback is optional. If this callback is not present, then the
- * driver must always have signaling enabled.
+ * This callback is mandatory.
*/
bool (*enable_signaling)(struct dma_fence *fence);
/**
* @wait:
*
- * Custom wait implementation, defaults to dma_fence_default_wait() if
- * not set.
+ * Custom wait implementation, or dma_fence_default_wait.
*
- * The dma_fence_default_wait implementation should work for any fence, as long
- * as @enable_signaling works correctly. This hook allows drivers to
- * have an optimized version for the case where a process context is
- * already available, e.g. if @enable_signaling for the general case
- * needs to set up a worker thread.
+ * Must not be NULL, set to dma_fence_default_wait for default implementation.
+ * the dma_fence_default_wait implementation should work for any fence, as long
+ * as enable_signaling works correctly.
*
* Must return -ERESTARTSYS if the wait is intr = true and the wait was
* interrupted, and remaining jiffies if fence has signaled, or 0 if wait
* which should be treated as if the fence is signaled. For example a hardware
* lockup could be reported like that.
*
- * This callback is optional.
+ * This callback is mandatory.
*/
signed long (*wait)(struct dma_fence *fence,
bool intr, signed long timeout);
*/
void (*release)(struct dma_fence *fence);
+ /**
+ * @fill_driver_data:
+ *
+ * Callback to fill in free-form debug info.
+ *
+ * Returns amount of bytes filled, or negative error on failure.
+ *
+ * This callback is optional.
+ */
+ int (*fill_driver_data)(struct dma_fence *fence, void *data, int size);
+
/**
* @fence_value_str:
*
* @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.
+ * sequence number. This should match what @fill_driver_data prints for
+ * the most recently signalled fence (assuming no delayed signalling).
*/
void (*timeline_value_str)(struct dma_fence *fence,
char *str, int size);