g2d_stamp_task(task, G2D_STAMP_STATE_TIMEOUT_FENCE, afbc);
- kref_put(&task->starter, g2d_queuework_task);
+ g2d_cancel_task(task);
};
static const char *g2d_fence_get_driver_name(struct dma_fence *fence)
return fence;
}
+
+static bool g2d_fence_has_error(struct g2d_layer *layer, int layer_idx)
+{
+ struct dma_fence *fence = layer->fence;
+ unsigned long flags;
+ bool err = false;
+
+ if (fence) {
+ spin_lock_irqsave(fence->lock, flags);
+ err = dma_fence_get_status_locked(fence) < 0;
+ spin_unlock_irqrestore(fence->lock, flags);
+ }
+
+ if (err) {
+ char name[32];
+
+ strlcpy(name, fence->ops->get_driver_name(fence), sizeof(name));
+
+ dev_err(layer->task->g2d_dev->dev,
+ "%s: Error fence of %s%d found: %s#%d\n", __func__,
+ (layer_idx < 0) ? "target" : "source",
+ layer_idx, name, fence->seqno);
+
+ return true;
+ }
+
+ return false;
+}
+
+bool g2d_task_has_error_fence(struct g2d_task *task)
+{
+ unsigned int i;
+
+ for (i = 0; i < task->num_source; i++)
+ if (g2d_fence_has_error(&task->source[i], i))
+ return false;
+
+ if (g2d_fence_has_error(&task->target, -1))
+ return true;
+
+ return false;
+}
struct sync_file *g2d_create_release_fence(struct g2d_device *g2d_dev,
struct g2d_task *task,
struct g2d_task_data *data);
+bool g2d_task_has_error_fence(struct g2d_task *task);
+
#endif /*__EXYNOS_G2D_FENCE_H__*/
del_timer(&task->fence_timer);
+ if (g2d_task_has_error_fence(task))
+ goto err_fence;
+
g2d_complete_commands(task);
/*
err_clk:
pm_runtime_put(g2d_dev->dev);
err_pm:
+err_fence:
__g2d_finish_task(task, false);
}
kref_put(&task->starter, g2d_task_direct_schedule);
}
+void g2d_cancel_task(struct g2d_task *task)
+{
+ __g2d_finish_task(task, false);
+}
+
void g2d_fence_callback(struct dma_fence *fence, struct dma_fence_cb *cb)
{
struct g2d_layer *layer = container_of(cb, struct g2d_layer, fence_cb);
void g2d_put_free_task(struct g2d_device *g2d_dev, struct g2d_task *task);
void g2d_start_task(struct g2d_task *task);
+void g2d_cancel_task(struct g2d_task *task);
void g2d_finish_task_with_id(struct g2d_device *g2d_dev,
unsigned int job_id, bool success);
void g2d_flush_all_tasks(struct g2d_device *g2d_dev);
g2d_invalidate_caches_task(task);
if (task->release_fence) {
+ if (is_task_state_error(task))
+ dma_fence_set_error(task->release_fence->fence, -EIO);
+
dma_fence_signal(task->release_fence->fence);
fput(task->release_fence->file);
}