aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2018-12-06 19:46:29 -0500
committerDave Airlie <airlied@redhat.com>2018-12-06 20:23:05 -0500
commite69aa5f9b97f7f871643336deb281db5cb14878b (patch)
tree1cc3fff133fe46c8e9b1c7c8f7c3840b56904912 /drivers
parent1f9a5dce3548d54d810b23e4e0b1d8c6d73a52d4 (diff)
parent0b258ed1a219a9776e8f6967eb34837ae0332e64 (diff)
Merge tag 'drm-misc-next-2018-12-06' of git://anongit.freedesktop.org/drm/drm-misc into drm-next
Final changes to drm-misc-next for v4.21: UAPI Changes: Core Changes: - Add dma_fence_get_stub to dma-buf, and use it in drm/syncobj. - Add and use DRM_MODESET_LOCK_BEGIN/END helpers. - Small fixes to drm_atomic_helper_resume(), drm_mode_setcrtc() and drm_atomic_helper_commit_duplicated_state() - Fix drm_atomic_state_helper.[c] extraction. Driver Changes: - Small fixes to tinydrm, vkms, meson, rcar-du, virtio, vkms, v3d, and pl111. - vc4: Allow scaling and YUV formats on cursor planes. - v3d: Enable use of the Texture Formatting Unit, and fix prime imports of buffers from other drivers. - Add support for the AUO G101EVN010 panel. - sun4i: Enable support for the H6 display engine. Signed-off-by: Dave Airlie <airlied@redhat.com> [airlied: added drm/v3d: fix broken build to the merge commit] From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/321be9d3-ab75-5f92-8193-e5113662edef@linux.intel.com
Diffstat (limited to 'drivers')
-rw-r--r--drivers/dma-buf/dma-fence.c36
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c2
-rw-r--r--drivers/gpu/drm/drm_atomic_helper.c217
-rw-r--r--drivers/gpu/drm/drm_atomic_state_helper.c157
-rw-r--r--drivers/gpu/drm/drm_color_mgmt.c14
-rw-r--r--drivers/gpu/drm/drm_crtc.c31
-rw-r--r--drivers/gpu/drm/drm_modeset_lock.c6
-rw-r--r--drivers/gpu/drm/drm_plane.c16
-rw-r--r--drivers/gpu/drm/drm_syncobj.c70
-rw-r--r--drivers/gpu/drm/i915/i915_gem_execbuffer.c2
-rw-r--r--drivers/gpu/drm/meson/meson_plane.c12
-rw-r--r--drivers/gpu/drm/meson/meson_viu.c27
-rw-r--r--drivers/gpu/drm/meson/meson_viu.h1
-rw-r--r--drivers/gpu/drm/panel/panel-simple.c27
-rw-r--r--drivers/gpu/drm/pl111/pl111_vexpress.c2
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_drv.c14
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_drv.h2
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_kms.c21
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_drv.c1
-rw-r--r--drivers/gpu/drm/tinydrm/repaper.c3
-rw-r--r--drivers/gpu/drm/v3d/v3d_bo.c1
-rw-r--r--drivers/gpu/drm/v3d/v3d_drv.c15
-rw-r--r--drivers/gpu/drm/v3d/v3d_drv.h32
-rw-r--r--drivers/gpu/drm/v3d/v3d_fence.c10
-rw-r--r--drivers/gpu/drm/v3d/v3d_gem.c187
-rw-r--r--drivers/gpu/drm/v3d/v3d_irq.c29
-rw-r--r--drivers/gpu/drm/v3d/v3d_regs.h49
-rw-r--r--drivers/gpu/drm/v3d/v3d_sched.c147
-rw-r--r--drivers/gpu/drm/v3d/v3d_trace.h121
-rw-r--r--drivers/gpu/drm/vc4/vc4_drv.h6
-rw-r--r--drivers/gpu/drm/vc4/vc4_gem.c2
-rw-r--r--drivers/gpu/drm/vc4/vc4_plane.c223
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_drv.h15
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_fence.c10
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_ioctl.c10
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_plane.c2
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_vq.c23
-rw-r--r--drivers/gpu/drm/vkms/vkms_plane.c9
38 files changed, 1043 insertions, 509 deletions
diff --git a/drivers/dma-buf/dma-fence.c b/drivers/dma-buf/dma-fence.c
index 1551ca7df394..136ec04d683f 100644
--- a/drivers/dma-buf/dma-fence.c
+++ b/drivers/dma-buf/dma-fence.c
@@ -30,13 +30,16 @@
30EXPORT_TRACEPOINT_SYMBOL(dma_fence_emit); 30EXPORT_TRACEPOINT_SYMBOL(dma_fence_emit);
31EXPORT_TRACEPOINT_SYMBOL(dma_fence_enable_signal); 31EXPORT_TRACEPOINT_SYMBOL(dma_fence_enable_signal);
32 32
33static DEFINE_SPINLOCK(dma_fence_stub_lock);
34static struct dma_fence dma_fence_stub;
35
33/* 36/*
34 * fence context counter: each execution context should have its own 37 * fence context counter: each execution context should have its own
35 * fence context, this allows checking if fences belong to the same 38 * fence context, this allows checking if fences belong to the same
36 * context or not. One device can have multiple separate contexts, 39 * context or not. One device can have multiple separate contexts,
37 * and they're used if some engine can run independently of another. 40 * and they're used if some engine can run independently of another.
38 */ 41 */
39static atomic64_t dma_fence_context_counter = ATOMIC64_INIT(0); 42static atomic64_t dma_fence_context_counter = ATOMIC64_INIT(1);
40 43
41/** 44/**
42 * DOC: DMA fences overview 45 * DOC: DMA fences overview
@@ -68,6 +71,37 @@ static atomic64_t dma_fence_context_counter = ATOMIC64_INIT(0);
68 * &dma_buf.resv pointer. 71 * &dma_buf.resv pointer.
69 */ 72 */
70 73
74static const char *dma_fence_stub_get_name(struct dma_fence *fence)
75{
76 return "stub";
77}
78
79static const struct dma_fence_ops dma_fence_stub_ops = {
80 .get_driver_name = dma_fence_stub_get_name,
81 .get_timeline_name = dma_fence_stub_get_name,
82};
83
84/**
85 * dma_fence_get_stub - return a signaled fence
86 *
87 * Return a stub fence which is already signaled.
88 */
89struct dma_fence *dma_fence_get_stub(void)
90{
91 spin_lock(&dma_fence_stub_lock);
92 if (!dma_fence_stub.ops) {
93 dma_fence_init(&dma_fence_stub,
94 &dma_fence_stub_ops,
95 &dma_fence_stub_lock,
96 0, 0);
97 dma_fence_signal_locked(&dma_fence_stub);
98 }
99 spin_unlock(&dma_fence_stub_lock);
100
101 return dma_fence_get(&dma_fence_stub);
102}
103EXPORT_SYMBOL(dma_fence_get_stub);
104
71/** 105/**
72 * dma_fence_context_alloc - allocate an array of fence contexts 106 * dma_fence_context_alloc - allocate an array of fence contexts
73 * @num: amount of contexts to allocate 107 * @num: amount of contexts to allocate
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
index 024dfbd87f11..dc54e9efd910 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
@@ -1193,7 +1193,7 @@ static void amdgpu_cs_post_dependencies(struct amdgpu_cs_parser *p)
1193 int i; 1193 int i;
1194 1194
1195 for (i = 0; i < p->num_post_dep_syncobjs; ++i) 1195 for (i = 0; i < p->num_post_dep_syncobjs; ++i)
1196 drm_syncobj_replace_fence(p->post_dep_syncobjs[i], 0, p->fence); 1196 drm_syncobj_replace_fence(p->post_dep_syncobjs[i], p->fence);
1197} 1197}
1198 1198
1199static int amdgpu_cs_submit(struct amdgpu_cs_parser *p, 1199static int amdgpu_cs_submit(struct amdgpu_cs_parser *p,
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 5ed12144ceb7..54e2ae614dcc 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -3131,27 +3131,104 @@ void drm_atomic_helper_shutdown(struct drm_device *dev)
3131 struct drm_modeset_acquire_ctx ctx; 3131 struct drm_modeset_acquire_ctx ctx;
3132 int ret; 3132 int ret;
3133 3133
3134 drm_modeset_acquire_init(&ctx, 0); 3134 DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, 0, ret);
3135 while (1) {
3136 ret = drm_modeset_lock_all_ctx(dev, &ctx);
3137 if (!ret)
3138 ret = __drm_atomic_helper_disable_all(dev, &ctx, true);
3139
3140 if (ret != -EDEADLK)
3141 break;
3142
3143 drm_modeset_backoff(&ctx);
3144 }
3145 3135
3136 ret = __drm_atomic_helper_disable_all(dev, &ctx, true);
3146 if (ret) 3137 if (ret)
3147 DRM_ERROR("Disabling all crtc's during unload failed with %i\n", ret); 3138 DRM_ERROR("Disabling all crtc's during unload failed with %i\n", ret);
3148 3139
3149 drm_modeset_drop_locks(&ctx); 3140 DRM_MODESET_LOCK_ALL_END(ctx, ret);
3150 drm_modeset_acquire_fini(&ctx);
3151} 3141}
3152EXPORT_SYMBOL(drm_atomic_helper_shutdown); 3142EXPORT_SYMBOL(drm_atomic_helper_shutdown);
3153 3143
3154/** 3144/**
3145 * drm_atomic_helper_duplicate_state - duplicate an atomic state object
3146 * @dev: DRM device
3147 * @ctx: lock acquisition context
3148 *
3149 * Makes a copy of the current atomic state by looping over all objects and
3150 * duplicating their respective states. This is used for example by suspend/
3151 * resume support code to save the state prior to suspend such that it can
3152 * be restored upon resume.
3153 *
3154 * Note that this treats atomic state as persistent between save and restore.
3155 * Drivers must make sure that this is possible and won't result in confusion
3156 * or erroneous behaviour.
3157 *
3158 * Note that if callers haven't already acquired all modeset locks this might
3159 * return -EDEADLK, which must be handled by calling drm_modeset_backoff().
3160 *
3161 * Returns:
3162 * A pointer to the copy of the atomic state object on success or an
3163 * ERR_PTR()-encoded error code on failure.
3164 *
3165 * See also:
3166 * drm_atomic_helper_suspend(), drm_atomic_helper_resume()
3167 */
3168struct drm_atomic_state *
3169drm_atomic_helper_duplicate_state(struct drm_device *dev,
3170 struct drm_modeset_acquire_ctx *ctx)
3171{
3172 struct drm_atomic_state *state;
3173 struct drm_connector *conn;
3174 struct drm_connector_list_iter conn_iter;
3175 struct drm_plane *plane;
3176 struct drm_crtc *crtc;
3177 int err = 0;
3178
3179 state = drm_atomic_state_alloc(dev);
3180 if (!state)
3181 return ERR_PTR(-ENOMEM);
3182
3183 state->acquire_ctx = ctx;
3184
3185 drm_for_each_crtc(crtc, dev) {
3186 struct drm_crtc_state *crtc_state;
3187
3188 crtc_state = drm_atomic_get_crtc_state(state, crtc);
3189 if (IS_ERR(crtc_state)) {
3190 err = PTR_ERR(crtc_state);
3191 goto free;
3192 }
3193 }
3194
3195 drm_for_each_plane(plane, dev) {
3196 struct drm_plane_state *plane_state;
3197
3198 plane_state = drm_atomic_get_plane_state(state, plane);
3199 if (IS_ERR(plane_state)) {
3200 err = PTR_ERR(plane_state);
3201 goto free;
3202 }
3203 }
3204
3205 drm_connector_list_iter_begin(dev, &conn_iter);
3206 drm_for_each_connector_iter(conn, &conn_iter) {
3207 struct drm_connector_state *conn_state;
3208
3209 conn_state = drm_atomic_get_connector_state(state, conn);
3210 if (IS_ERR(conn_state)) {
3211 err = PTR_ERR(conn_state);
3212 drm_connector_list_iter_end(&conn_iter);
3213 goto free;
3214 }
3215 }
3216 drm_connector_list_iter_end(&conn_iter);
3217
3218 /* clear the acquire context so that it isn't accidentally reused */
3219 state->acquire_ctx = NULL;
3220
3221free:
3222 if (err < 0) {
3223 drm_atomic_state_put(state);
3224 state = ERR_PTR(err);
3225 }
3226
3227 return state;
3228}
3229EXPORT_SYMBOL(drm_atomic_helper_duplicate_state);
3230
3231/**
3155 * drm_atomic_helper_suspend - subsystem-level suspend helper 3232 * drm_atomic_helper_suspend - subsystem-level suspend helper
3156 * @dev: DRM device 3233 * @dev: DRM device
3157 * 3234 *
@@ -3182,14 +3259,10 @@ struct drm_atomic_state *drm_atomic_helper_suspend(struct drm_device *dev)
3182 struct drm_atomic_state *state; 3259 struct drm_atomic_state *state;
3183 int err; 3260 int err;
3184 3261
3185 drm_modeset_acquire_init(&ctx, 0); 3262 /* This can never be returned, but it makes the compiler happy */
3263 state = ERR_PTR(-EINVAL);
3186 3264
3187retry: 3265 DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, 0, err);
3188 err = drm_modeset_lock_all_ctx(dev, &ctx);
3189 if (err < 0) {
3190 state = ERR_PTR(err);
3191 goto unlock;
3192 }
3193 3266
3194 state = drm_atomic_helper_duplicate_state(dev, &ctx); 3267 state = drm_atomic_helper_duplicate_state(dev, &ctx);
3195 if (IS_ERR(state)) 3268 if (IS_ERR(state))
@@ -3203,13 +3276,10 @@ retry:
3203 } 3276 }
3204 3277
3205unlock: 3278unlock:
3206 if (PTR_ERR(state) == -EDEADLK) { 3279 DRM_MODESET_LOCK_ALL_END(ctx, err);
3207 drm_modeset_backoff(&ctx); 3280 if (err)
3208 goto retry; 3281 return ERR_PTR(err);
3209 }
3210 3282
3211 drm_modeset_drop_locks(&ctx);
3212 drm_modeset_acquire_fini(&ctx);
3213 return state; 3283 return state;
3214} 3284}
3215EXPORT_SYMBOL(drm_atomic_helper_suspend); 3285EXPORT_SYMBOL(drm_atomic_helper_suspend);
@@ -3232,7 +3302,7 @@ EXPORT_SYMBOL(drm_atomic_helper_suspend);
3232int drm_atomic_helper_commit_duplicated_state(struct drm_atomic_state *state, 3302int drm_atomic_helper_commit_duplicated_state(struct drm_atomic_state *state,
3233 struct drm_modeset_acquire_ctx *ctx) 3303 struct drm_modeset_acquire_ctx *ctx)
3234{ 3304{
3235 int i; 3305 int i, ret;
3236 struct drm_plane *plane; 3306 struct drm_plane *plane;
3237 struct drm_plane_state *new_plane_state; 3307 struct drm_plane_state *new_plane_state;
3238 struct drm_connector *connector; 3308 struct drm_connector *connector;
@@ -3251,7 +3321,11 @@ int drm_atomic_helper_commit_duplicated_state(struct drm_atomic_state *state,
3251 for_each_new_connector_in_state(state, connector, new_conn_state, i) 3321 for_each_new_connector_in_state(state, connector, new_conn_state, i)
3252 state->connectors[i].old_state = connector->state; 3322 state->connectors[i].old_state = connector->state;
3253 3323
3254 return drm_atomic_commit(state); 3324 ret = drm_atomic_commit(state);
3325
3326 state->acquire_ctx = NULL;
3327
3328 return ret;
3255} 3329}
3256EXPORT_SYMBOL(drm_atomic_helper_commit_duplicated_state); 3330EXPORT_SYMBOL(drm_atomic_helper_commit_duplicated_state);
3257 3331
@@ -3279,23 +3353,12 @@ int drm_atomic_helper_resume(struct drm_device *dev,
3279 3353
3280 drm_mode_config_reset(dev); 3354 drm_mode_config_reset(dev);
3281 3355
3282 drm_modeset_acquire_init(&ctx, 0); 3356 DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, 0, err);
3283 while (1) {
3284 err = drm_modeset_lock_all_ctx(dev, &ctx);
3285 if (err)
3286 goto out;
3287 3357
3288 err = drm_atomic_helper_commit_duplicated_state(state, &ctx); 3358 err = drm_atomic_helper_commit_duplicated_state(state, &ctx);
3289out:
3290 if (err != -EDEADLK)
3291 break;
3292
3293 drm_modeset_backoff(&ctx);
3294 }
3295 3359
3360 DRM_MODESET_LOCK_ALL_END(ctx, err);
3296 drm_atomic_state_put(state); 3361 drm_atomic_state_put(state);
3297 drm_modeset_drop_locks(&ctx);
3298 drm_modeset_acquire_fini(&ctx);
3299 3362
3300 return err; 3363 return err;
3301} 3364}
@@ -3434,3 +3497,73 @@ fail:
3434 return ret; 3497 return ret;
3435} 3498}
3436EXPORT_SYMBOL(drm_atomic_helper_page_flip_target); 3499EXPORT_SYMBOL(drm_atomic_helper_page_flip_target);
3500
3501/**
3502 * drm_atomic_helper_legacy_gamma_set - set the legacy gamma correction table
3503 * @crtc: CRTC object
3504 * @red: red correction table
3505 * @green: green correction table
3506 * @blue: green correction table
3507 * @size: size of the tables
3508 * @ctx: lock acquire context
3509 *
3510 * Implements support for legacy gamma correction table for drivers
3511 * that support color management through the DEGAMMA_LUT/GAMMA_LUT
3512 * properties. See drm_crtc_enable_color_mgmt() and the containing chapter for
3513 * how the atomic color management and gamma tables work.
3514 */
3515int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc,
3516 u16 *red, u16 *green, u16 *blue,
3517 uint32_t size,
3518 struct drm_modeset_acquire_ctx *ctx)
3519{
3520 struct drm_device *dev = crtc->dev;
3521 struct drm_atomic_state *state;
3522 struct drm_crtc_state *crtc_state;
3523 struct drm_property_blob *blob = NULL;
3524 struct drm_color_lut *blob_data;
3525 int i, ret = 0;
3526 bool replaced;
3527
3528 state = drm_atomic_state_alloc(crtc->dev);
3529 if (!state)
3530 return -ENOMEM;
3531
3532 blob = drm_property_create_blob(dev,
3533 sizeof(struct drm_color_lut) * size,
3534 NULL);
3535 if (IS_ERR(blob)) {
3536 ret = PTR_ERR(blob);
3537 blob = NULL;
3538 goto fail;
3539 }
3540
3541 /* Prepare GAMMA_LUT with the legacy values. */
3542 blob_data = blob->data;
3543 for (i = 0; i < size; i++) {
3544 blob_data[i].red = red[i];
3545 blob_data[i].green = green[i];
3546 blob_data[i].blue = blue[i];
3547 }
3548
3549 state->acquire_ctx = ctx;
3550 crtc_state = drm_atomic_get_crtc_state(state, crtc);
3551 if (IS_ERR(crtc_state)) {
3552 ret = PTR_ERR(crtc_state);
3553 goto fail;
3554 }
3555
3556 /* Reset DEGAMMA_LUT and CTM properties. */
3557 replaced = drm_property_replace_blob(&crtc_state->degamma_lut, NULL);
3558 replaced |= drm_property_replace_blob(&crtc_state->ctm, NULL);
3559 replaced |= drm_property_replace_blob(&crtc_state->gamma_lut, blob);
3560 crtc_state->color_mgmt_changed |= replaced;
3561
3562 ret = drm_atomic_commit(state);
3563
3564fail:
3565 drm_atomic_state_put(state);
3566 drm_property_blob_put(blob);
3567 return ret;
3568}
3569EXPORT_SYMBOL(drm_atomic_helper_legacy_gamma_set);
diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c
index 3ba996069d69..60bd7d708e35 100644
--- a/drivers/gpu/drm/drm_atomic_state_helper.c
+++ b/drivers/gpu/drm/drm_atomic_state_helper.c
@@ -394,93 +394,6 @@ drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector)
394EXPORT_SYMBOL(drm_atomic_helper_connector_duplicate_state); 394EXPORT_SYMBOL(drm_atomic_helper_connector_duplicate_state);
395 395
396/** 396/**
397 * drm_atomic_helper_duplicate_state - duplicate an atomic state object
398 * @dev: DRM device
399 * @ctx: lock acquisition context
400 *
401 * Makes a copy of the current atomic state by looping over all objects and
402 * duplicating their respective states. This is used for example by suspend/
403 * resume support code to save the state prior to suspend such that it can
404 * be restored upon resume.
405 *
406 * Note that this treats atomic state as persistent between save and restore.
407 * Drivers must make sure that this is possible and won't result in confusion
408 * or erroneous behaviour.
409 *
410 * Note that if callers haven't already acquired all modeset locks this might
411 * return -EDEADLK, which must be handled by calling drm_modeset_backoff().
412 *
413 * Returns:
414 * A pointer to the copy of the atomic state object on success or an
415 * ERR_PTR()-encoded error code on failure.
416 *
417 * See also:
418 * drm_atomic_helper_suspend(), drm_atomic_helper_resume()
419 */
420struct drm_atomic_state *
421drm_atomic_helper_duplicate_state(struct drm_device *dev,
422 struct drm_modeset_acquire_ctx *ctx)
423{
424 struct drm_atomic_state *state;
425 struct drm_connector *conn;
426 struct drm_connector_list_iter conn_iter;
427 struct drm_plane *plane;
428 struct drm_crtc *crtc;
429 int err = 0;
430
431 state = drm_atomic_state_alloc(dev);
432 if (!state)
433 return ERR_PTR(-ENOMEM);
434
435 state->acquire_ctx = ctx;
436
437 drm_for_each_crtc(crtc, dev) {
438 struct drm_crtc_state *crtc_state;
439
440 crtc_state = drm_atomic_get_crtc_state(state, crtc);
441 if (IS_ERR(crtc_state)) {
442 err = PTR_ERR(crtc_state);
443 goto free;
444 }
445 }
446
447 drm_for_each_plane(plane, dev) {
448 struct drm_plane_state *plane_state;
449
450 plane_state = drm_atomic_get_plane_state(state, plane);
451 if (IS_ERR(plane_state)) {
452 err = PTR_ERR(plane_state);
453 goto free;
454 }
455 }
456
457 drm_connector_list_iter_begin(dev, &conn_iter);
458 drm_for_each_connector_iter(conn, &conn_iter) {
459 struct drm_connector_state *conn_state;
460
461 conn_state = drm_atomic_get_connector_state(state, conn);
462 if (IS_ERR(conn_state)) {
463 err = PTR_ERR(conn_state);
464 drm_connector_list_iter_end(&conn_iter);
465 goto free;
466 }
467 }
468 drm_connector_list_iter_end(&conn_iter);
469
470 /* clear the acquire context so that it isn't accidentally reused */
471 state->acquire_ctx = NULL;
472
473free:
474 if (err < 0) {
475 drm_atomic_state_put(state);
476 state = ERR_PTR(err);
477 }
478
479 return state;
480}
481EXPORT_SYMBOL(drm_atomic_helper_duplicate_state);
482
483/**
484 * __drm_atomic_helper_connector_destroy_state - release connector state 397 * __drm_atomic_helper_connector_destroy_state - release connector state
485 * @state: connector state object to release 398 * @state: connector state object to release
486 * 399 *
@@ -516,76 +429,6 @@ void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
516EXPORT_SYMBOL(drm_atomic_helper_connector_destroy_state); 429EXPORT_SYMBOL(drm_atomic_helper_connector_destroy_state);
517 430
518/** 431/**
519 * drm_atomic_helper_legacy_gamma_set - set the legacy gamma correction table
520 * @crtc: CRTC object
521 * @red: red correction table
522 * @green: green correction table
523 * @blue: green correction table
524 * @size: size of the tables
525 * @ctx: lock acquire context
526 *
527 * Implements support for legacy gamma correction table for drivers
528 * that support color management through the DEGAMMA_LUT/GAMMA_LUT
529 * properties. See drm_crtc_enable_color_mgmt() and the containing chapter for
530 * how the atomic color management and gamma tables work.
531 */
532int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc,
533 u16 *red, u16 *green, u16 *blue,
534 uint32_t size,
535 struct drm_modeset_acquire_ctx *ctx)
536{
537 struct drm_device *dev = crtc->dev;
538 struct drm_atomic_state *state;
539 struct drm_crtc_state *crtc_state;
540 struct drm_property_blob *blob = NULL;
541 struct drm_color_lut *blob_data;
542 int i, ret = 0;
543 bool replaced;
544
545 state = drm_atomic_state_alloc(crtc->dev);
546 if (!state)
547 return -ENOMEM;
548
549 blob = drm_property_create_blob(dev,
550 sizeof(struct drm_color_lut) * size,
551 NULL);
552 if (IS_ERR(blob)) {
553 ret = PTR_ERR(blob);
554 blob = NULL;
555 goto fail;
556 }
557
558 /* Prepare GAMMA_LUT with the legacy values. */
559 blob_data = blob->data;
560 for (i = 0; i < size; i++) {
561 blob_data[i].red = red[i];
562 blob_data[i].green = green[i];
563 blob_data[i].blue = blue[i];
564 }
565
566 state->acquire_ctx = ctx;
567 crtc_state = drm_atomic_get_crtc_state(state, crtc);
568 if (IS_ERR(crtc_state)) {
569 ret = PTR_ERR(crtc_state);
570 goto fail;
571 }
572
573 /* Reset DEGAMMA_LUT and CTM properties. */
574 replaced = drm_property_replace_blob(&crtc_state->degamma_lut, NULL);
575 replaced |= drm_property_replace_blob(&crtc_state->ctm, NULL);
576 replaced |= drm_property_replace_blob(&crtc_state->gamma_lut, blob);
577 crtc_state->color_mgmt_changed |= replaced;
578
579 ret = drm_atomic_commit(state);
580
581fail:
582 drm_atomic_state_put(state);
583 drm_property_blob_put(blob);
584 return ret;
585}
586EXPORT_SYMBOL(drm_atomic_helper_legacy_gamma_set);
587
588/**
589 * __drm_atomic_helper_private_duplicate_state - copy atomic private state 432 * __drm_atomic_helper_private_duplicate_state - copy atomic private state
590 * @obj: CRTC object 433 * @obj: CRTC object
591 * @state: new private object state 434 * @state: new private object state
diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c
index 581cc3788223..07dcf47daafe 100644
--- a/drivers/gpu/drm/drm_color_mgmt.c
+++ b/drivers/gpu/drm/drm_color_mgmt.c
@@ -255,11 +255,7 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev,
255 if (crtc_lut->gamma_size != crtc->gamma_size) 255 if (crtc_lut->gamma_size != crtc->gamma_size)
256 return -EINVAL; 256 return -EINVAL;
257 257
258 drm_modeset_acquire_init(&ctx, 0); 258 DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, 0, ret);
259retry:
260 ret = drm_modeset_lock_all_ctx(dev, &ctx);
261 if (ret)
262 goto out;
263 259
264 size = crtc_lut->gamma_size * (sizeof(uint16_t)); 260 size = crtc_lut->gamma_size * (sizeof(uint16_t));
265 r_base = crtc->gamma_store; 261 r_base = crtc->gamma_store;
@@ -284,13 +280,7 @@ retry:
284 crtc->gamma_size, &ctx); 280 crtc->gamma_size, &ctx);
285 281
286out: 282out:
287 if (ret == -EDEADLK) { 283 DRM_MODESET_LOCK_ALL_END(ctx, ret);
288 drm_modeset_backoff(&ctx);
289 goto retry;
290 }
291 drm_modeset_drop_locks(&ctx);
292 drm_modeset_acquire_fini(&ctx);
293
294 return ret; 284 return ret;
295 285
296} 286}
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 6f8ddfcfaba5..1593dd6cdfb7 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -572,9 +572,9 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
572 struct drm_mode_crtc *crtc_req = data; 572 struct drm_mode_crtc *crtc_req = data;
573 struct drm_crtc *crtc; 573 struct drm_crtc *crtc;
574 struct drm_plane *plane; 574 struct drm_plane *plane;
575 struct drm_connector **connector_set, *connector; 575 struct drm_connector **connector_set = NULL, *connector;
576 struct drm_framebuffer *fb; 576 struct drm_framebuffer *fb = NULL;
577 struct drm_display_mode *mode; 577 struct drm_display_mode *mode = NULL;
578 struct drm_mode_set set; 578 struct drm_mode_set set;
579 uint32_t __user *set_connectors_ptr; 579 uint32_t __user *set_connectors_ptr;
580 struct drm_modeset_acquire_ctx ctx; 580 struct drm_modeset_acquire_ctx ctx;
@@ -601,15 +601,8 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
601 plane = crtc->primary; 601 plane = crtc->primary;
602 602
603 mutex_lock(&crtc->dev->mode_config.mutex); 603 mutex_lock(&crtc->dev->mode_config.mutex);
604 drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE); 604 DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx,
605retry: 605 DRM_MODESET_ACQUIRE_INTERRUPTIBLE, ret);
606 connector_set = NULL;
607 fb = NULL;
608 mode = NULL;
609
610 ret = drm_modeset_lock_all_ctx(crtc->dev, &ctx);
611 if (ret)
612 goto out;
613 606
614 if (crtc_req->mode_valid) { 607 if (crtc_req->mode_valid) {
615 /* If we have a mode we need a framebuffer. */ 608 /* If we have a mode we need a framebuffer. */
@@ -768,13 +761,13 @@ out:
768 } 761 }
769 kfree(connector_set); 762 kfree(connector_set);
770 drm_mode_destroy(dev, mode); 763 drm_mode_destroy(dev, mode);
771 if (ret == -EDEADLK) { 764
772 ret = drm_modeset_backoff(&ctx); 765 /* In case we need to retry... */
773 if (!ret) 766 connector_set = NULL;
774 goto retry; 767 fb = NULL;
775 } 768 mode = NULL;
776 drm_modeset_drop_locks(&ctx); 769
777 drm_modeset_acquire_fini(&ctx); 770 DRM_MODESET_LOCK_ALL_END(ctx, ret);
778 mutex_unlock(&crtc->dev->mode_config.mutex); 771 mutex_unlock(&crtc->dev->mode_config.mutex);
779 772
780 return ret; 773 return ret;
diff --git a/drivers/gpu/drm/drm_modeset_lock.c b/drivers/gpu/drm/drm_modeset_lock.c
index 8a5100685875..51f534db9107 100644
--- a/drivers/gpu/drm/drm_modeset_lock.c
+++ b/drivers/gpu/drm/drm_modeset_lock.c
@@ -56,6 +56,10 @@
56 * drm_modeset_drop_locks(ctx); 56 * drm_modeset_drop_locks(ctx);
57 * drm_modeset_acquire_fini(ctx); 57 * drm_modeset_acquire_fini(ctx);
58 * 58 *
59 * For convenience this control flow is implemented in
60 * DRM_MODESET_LOCK_ALL_BEGIN() and DRM_MODESET_LOCK_ALL_END() for the case
61 * where all modeset locks need to be taken through drm_modeset_lock_all_ctx().
62 *
59 * If all that is needed is a single modeset lock, then the &struct 63 * If all that is needed is a single modeset lock, then the &struct
60 * drm_modeset_acquire_ctx is not needed and the locking can be simplified 64 * drm_modeset_acquire_ctx is not needed and the locking can be simplified
61 * by passing a NULL instead of ctx in the drm_modeset_lock() call or 65 * by passing a NULL instead of ctx in the drm_modeset_lock() call or
@@ -383,6 +387,8 @@ EXPORT_SYMBOL(drm_modeset_unlock);
383 * Locks acquired with this function should be released by calling the 387 * Locks acquired with this function should be released by calling the
384 * drm_modeset_drop_locks() function on @ctx. 388 * drm_modeset_drop_locks() function on @ctx.
385 * 389 *
390 * See also: DRM_MODESET_LOCK_ALL_BEGIN() and DRM_MODESET_LOCK_ALL_END()
391 *
386 * Returns: 0 on success or a negative error-code on failure. 392 * Returns: 0 on success or a negative error-code on failure.
387 */ 393 */
388int drm_modeset_lock_all_ctx(struct drm_device *dev, 394int drm_modeset_lock_all_ctx(struct drm_device *dev,
diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c
index 679455e36829..5f650d8fc66b 100644
--- a/drivers/gpu/drm/drm_plane.c
+++ b/drivers/gpu/drm/drm_plane.c
@@ -767,11 +767,8 @@ static int setplane_internal(struct drm_plane *plane,
767 struct drm_modeset_acquire_ctx ctx; 767 struct drm_modeset_acquire_ctx ctx;
768 int ret; 768 int ret;
769 769
770 drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE); 770 DRM_MODESET_LOCK_ALL_BEGIN(plane->dev, ctx,
771retry: 771 DRM_MODESET_ACQUIRE_INTERRUPTIBLE, ret);
772 ret = drm_modeset_lock_all_ctx(plane->dev, &ctx);
773 if (ret)
774 goto fail;
775 772
776 if (drm_drv_uses_atomic_modeset(plane->dev)) 773 if (drm_drv_uses_atomic_modeset(plane->dev))
777 ret = __setplane_atomic(plane, crtc, fb, 774 ret = __setplane_atomic(plane, crtc, fb,
@@ -782,14 +779,7 @@ retry:
782 crtc_x, crtc_y, crtc_w, crtc_h, 779 crtc_x, crtc_y, crtc_w, crtc_h,
783 src_x, src_y, src_w, src_h, &ctx); 780 src_x, src_y, src_w, src_h, &ctx);
784 781
785fail: 782 DRM_MODESET_LOCK_ALL_END(ctx, ret);
786 if (ret == -EDEADLK) {
787 ret = drm_modeset_backoff(&ctx);
788 if (!ret)
789 goto retry;
790 }
791 drm_modeset_drop_locks(&ctx);
792 drm_modeset_acquire_fini(&ctx);
793 783
794 return ret; 784 return ret;
795} 785}
diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c
index e2c5b3ca4824..db30a0e89db8 100644
--- a/drivers/gpu/drm/drm_syncobj.c
+++ b/drivers/gpu/drm/drm_syncobj.c
@@ -56,22 +56,6 @@
56#include "drm_internal.h" 56#include "drm_internal.h"
57#include <drm/drm_syncobj.h> 57#include <drm/drm_syncobj.h>
58 58
59struct drm_syncobj_stub_fence {
60 struct dma_fence base;
61 spinlock_t lock;
62};
63
64static const char *drm_syncobj_stub_fence_get_name(struct dma_fence *fence)
65{
66 return "syncobjstub";
67}
68
69static const struct dma_fence_ops drm_syncobj_stub_fence_ops = {
70 .get_driver_name = drm_syncobj_stub_fence_get_name,
71 .get_timeline_name = drm_syncobj_stub_fence_get_name,
72};
73
74
75/** 59/**
76 * drm_syncobj_find - lookup and reference a sync object. 60 * drm_syncobj_find - lookup and reference a sync object.
77 * @file_private: drm file private pointer 61 * @file_private: drm file private pointer
@@ -156,13 +140,11 @@ void drm_syncobj_remove_callback(struct drm_syncobj *syncobj,
156/** 140/**
157 * drm_syncobj_replace_fence - replace fence in a sync object. 141 * drm_syncobj_replace_fence - replace fence in a sync object.
158 * @syncobj: Sync object to replace fence in 142 * @syncobj: Sync object to replace fence in
159 * @point: timeline point
160 * @fence: fence to install in sync file. 143 * @fence: fence to install in sync file.
161 * 144 *
162 * This replaces the fence on a sync object, or a timeline point fence. 145 * This replaces the fence on a sync object.
163 */ 146 */
164void drm_syncobj_replace_fence(struct drm_syncobj *syncobj, 147void drm_syncobj_replace_fence(struct drm_syncobj *syncobj,
165 u64 point,
166 struct dma_fence *fence) 148 struct dma_fence *fence)
167{ 149{
168 struct dma_fence *old_fence; 150 struct dma_fence *old_fence;
@@ -190,23 +172,18 @@ void drm_syncobj_replace_fence(struct drm_syncobj *syncobj,
190} 172}
191EXPORT_SYMBOL(drm_syncobj_replace_fence); 173EXPORT_SYMBOL(drm_syncobj_replace_fence);
192 174
193static int drm_syncobj_assign_null_handle(struct drm_syncobj *syncobj) 175/**
176 * drm_syncobj_assign_null_handle - assign a stub fence to the sync object
177 * @syncobj: sync object to assign the fence on
178 *
179 * Assign a already signaled stub fence to the sync object.
180 */
181static void drm_syncobj_assign_null_handle(struct drm_syncobj *syncobj)
194{ 182{
195 struct drm_syncobj_stub_fence *fence; 183 struct dma_fence *fence = dma_fence_get_stub();
196 fence = kzalloc(sizeof(*fence), GFP_KERNEL);
197 if (fence == NULL)
198 return -ENOMEM;
199
200 spin_lock_init(&fence->lock);
201 dma_fence_init(&fence->base, &drm_syncobj_stub_fence_ops,
202 &fence->lock, 0, 0);
203 dma_fence_signal(&fence->base);
204
205 drm_syncobj_replace_fence(syncobj, 0, &fence->base);
206 184
207 dma_fence_put(&fence->base); 185 drm_syncobj_replace_fence(syncobj, fence);
208 186 dma_fence_put(fence);
209 return 0;
210} 187}
211 188
212/** 189/**
@@ -254,7 +231,7 @@ void drm_syncobj_free(struct kref *kref)
254 struct drm_syncobj *syncobj = container_of(kref, 231 struct drm_syncobj *syncobj = container_of(kref,
255 struct drm_syncobj, 232 struct drm_syncobj,
256 refcount); 233 refcount);
257 drm_syncobj_replace_fence(syncobj, 0, NULL); 234 drm_syncobj_replace_fence(syncobj, NULL);
258 kfree(syncobj); 235 kfree(syncobj);
259} 236}
260EXPORT_SYMBOL(drm_syncobj_free); 237EXPORT_SYMBOL(drm_syncobj_free);
@@ -274,7 +251,6 @@ EXPORT_SYMBOL(drm_syncobj_free);
274int drm_syncobj_create(struct drm_syncobj **out_syncobj, uint32_t flags, 251int drm_syncobj_create(struct drm_syncobj **out_syncobj, uint32_t flags,
275 struct dma_fence *fence) 252 struct dma_fence *fence)
276{ 253{
277 int ret;
278 struct drm_syncobj *syncobj; 254 struct drm_syncobj *syncobj;
279 255
280 syncobj = kzalloc(sizeof(struct drm_syncobj), GFP_KERNEL); 256 syncobj = kzalloc(sizeof(struct drm_syncobj), GFP_KERNEL);
@@ -285,16 +261,11 @@ int drm_syncobj_create(struct drm_syncobj **out_syncobj, uint32_t flags,
285 INIT_LIST_HEAD(&syncobj->cb_list); 261 INIT_LIST_HEAD(&syncobj->cb_list);
286 spin_lock_init(&syncobj->lock); 262 spin_lock_init(&syncobj->lock);
287 263
288 if (flags & DRM_SYNCOBJ_CREATE_SIGNALED) { 264 if (flags & DRM_SYNCOBJ_CREATE_SIGNALED)
289 ret = drm_syncobj_assign_null_handle(syncobj); 265 drm_syncobj_assign_null_handle(syncobj);
290 if (ret < 0) {
291 drm_syncobj_put(syncobj);
292 return ret;
293 }
294 }
295 266
296 if (fence) 267 if (fence)
297 drm_syncobj_replace_fence(syncobj, 0, fence); 268 drm_syncobj_replace_fence(syncobj, fence);
298 269
299 *out_syncobj = syncobj; 270 *out_syncobj = syncobj;
300 return 0; 271 return 0;
@@ -479,7 +450,7 @@ static int drm_syncobj_import_sync_file_fence(struct drm_file *file_private,
479 return -ENOENT; 450 return -ENOENT;
480 } 451 }
481 452
482 drm_syncobj_replace_fence(syncobj, 0, fence); 453 drm_syncobj_replace_fence(syncobj, fence);
483 dma_fence_put(fence); 454 dma_fence_put(fence);
484 drm_syncobj_put(syncobj); 455 drm_syncobj_put(syncobj);
485 return 0; 456 return 0;
@@ -950,7 +921,7 @@ drm_syncobj_reset_ioctl(struct drm_device *dev, void *data,
950 return ret; 921 return ret;
951 922
952 for (i = 0; i < args->count_handles; i++) 923 for (i = 0; i < args->count_handles; i++)
953 drm_syncobj_replace_fence(syncobjs[i], 0, NULL); 924 drm_syncobj_replace_fence(syncobjs[i], NULL);
954 925
955 drm_syncobj_array_free(syncobjs, args->count_handles); 926 drm_syncobj_array_free(syncobjs, args->count_handles);
956 927
@@ -982,11 +953,8 @@ drm_syncobj_signal_ioctl(struct drm_device *dev, void *data,
982 if (ret < 0) 953 if (ret < 0)
983 return ret; 954 return ret;
984 955
985 for (i = 0; i < args->count_handles; i++) { 956 for (i = 0; i < args->count_handles; i++)
986 ret = drm_syncobj_assign_null_handle(syncobjs[i]); 957 drm_syncobj_assign_null_handle(syncobjs[i]);
987 if (ret < 0)
988 break;
989 }
990 958
991 drm_syncobj_array_free(syncobjs, args->count_handles); 959 drm_syncobj_array_free(syncobjs, args->count_handles);
992 960
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index d4fac09095f8..10a4afb4f235 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -2191,7 +2191,7 @@ signal_fence_array(struct i915_execbuffer *eb,
2191 if (!(flags & I915_EXEC_FENCE_SIGNAL)) 2191 if (!(flags & I915_EXEC_FENCE_SIGNAL))
2192 continue; 2192 continue;
2193 2193
2194 drm_syncobj_replace_fence(syncobj, 0, fence); 2194 drm_syncobj_replace_fence(syncobj, fence);
2195 } 2195 }
2196} 2196}
2197 2197
diff --git a/drivers/gpu/drm/meson/meson_plane.c b/drivers/gpu/drm/meson/meson_plane.c
index 8ee2cf9e47cd..6119a0224278 100644
--- a/drivers/gpu/drm/meson/meson_plane.c
+++ b/drivers/gpu/drm/meson/meson_plane.c
@@ -80,6 +80,7 @@
80struct meson_plane { 80struct meson_plane {
81 struct drm_plane base; 81 struct drm_plane base;
82 struct meson_drm *priv; 82 struct meson_drm *priv;
83 bool enabled;
83}; 84};
84#define to_meson_plane(x) container_of(x, struct meson_plane, base) 85#define to_meson_plane(x) container_of(x, struct meson_plane, base)
85 86
@@ -304,6 +305,15 @@ static void meson_plane_atomic_update(struct drm_plane *plane,
304 priv->viu.osd1_stride = fb->pitches[0]; 305 priv->viu.osd1_stride = fb->pitches[0];
305 priv->viu.osd1_height = fb->height; 306 priv->viu.osd1_height = fb->height;
306 307
308 if (!meson_plane->enabled) {
309 /* Reset OSD1 before enabling it on GXL+ SoCs */
310 if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
311 meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
312 meson_viu_osd1_reset(priv);
313
314 meson_plane->enabled = true;
315 }
316
307 spin_unlock_irqrestore(&priv->drm->event_lock, flags); 317 spin_unlock_irqrestore(&priv->drm->event_lock, flags);
308} 318}
309 319
@@ -317,6 +327,8 @@ static void meson_plane_atomic_disable(struct drm_plane *plane,
317 writel_bits_relaxed(VPP_OSD1_POSTBLEND, 0, 327 writel_bits_relaxed(VPP_OSD1_POSTBLEND, 0,
318 priv->io_base + _REG(VPP_MISC)); 328 priv->io_base + _REG(VPP_MISC));
319 329
330 meson_plane->enabled = false;
331
320} 332}
321 333
322static const struct drm_plane_helper_funcs meson_plane_helper_funcs = { 334static const struct drm_plane_helper_funcs meson_plane_helper_funcs = {
diff --git a/drivers/gpu/drm/meson/meson_viu.c b/drivers/gpu/drm/meson/meson_viu.c
index 2dffb987ec65..0ba87ff95530 100644
--- a/drivers/gpu/drm/meson/meson_viu.c
+++ b/drivers/gpu/drm/meson/meson_viu.c
@@ -296,6 +296,33 @@ static void meson_viu_load_matrix(struct meson_drm *priv)
296 true); 296 true);
297} 297}
298 298
299/* VIU OSD1 Reset as workaround for GXL+ Alpha OSD Bug */
300void meson_viu_osd1_reset(struct meson_drm *priv)
301{
302 uint32_t osd1_fifo_ctrl_stat, osd1_ctrl_stat2;
303
304 /* Save these 2 registers state */
305 osd1_fifo_ctrl_stat = readl_relaxed(
306 priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT));
307 osd1_ctrl_stat2 = readl_relaxed(
308 priv->io_base + _REG(VIU_OSD1_CTRL_STAT2));
309
310 /* Reset OSD1 */
311 writel_bits_relaxed(BIT(0), BIT(0),
312 priv->io_base + _REG(VIU_SW_RESET));
313 writel_bits_relaxed(BIT(0), 0,
314 priv->io_base + _REG(VIU_SW_RESET));
315
316 /* Rewrite these registers state lost in the reset */
317 writel_relaxed(osd1_fifo_ctrl_stat,
318 priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT));
319 writel_relaxed(osd1_ctrl_stat2,
320 priv->io_base + _REG(VIU_OSD1_CTRL_STAT2));
321
322 /* Reload the conversion matrix */
323 meson_viu_load_matrix(priv);
324}
325
299void meson_viu_init(struct meson_drm *priv) 326void meson_viu_init(struct meson_drm *priv)
300{ 327{
301 uint32_t reg; 328 uint32_t reg;
diff --git a/drivers/gpu/drm/meson/meson_viu.h b/drivers/gpu/drm/meson/meson_viu.h
index 073b1910bd1b..0f84bddd2ff0 100644
--- a/drivers/gpu/drm/meson/meson_viu.h
+++ b/drivers/gpu/drm/meson/meson_viu.h
@@ -59,6 +59,7 @@
59#define OSD_REPLACE_EN BIT(14) 59#define OSD_REPLACE_EN BIT(14)
60#define OSD_REPLACE_SHIFT 6 60#define OSD_REPLACE_SHIFT 6
61 61
62void meson_viu_osd1_reset(struct meson_drm *priv);
62void meson_viu_init(struct meson_drm *priv); 63void meson_viu_init(struct meson_drm *priv);
63 64
64#endif /* __MESON_VIU_H */ 65#endif /* __MESON_VIU_H */
diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
index 5fbee837b0db..9c69e739a524 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -618,6 +618,30 @@ static const struct panel_desc auo_g070vvn01 = {
618 }, 618 },
619}; 619};
620 620
621static const struct drm_display_mode auo_g101evn010_mode = {
622 .clock = 68930,
623 .hdisplay = 1280,
624 .hsync_start = 1280 + 82,
625 .hsync_end = 1280 + 82 + 2,
626 .htotal = 1280 + 82 + 2 + 84,
627 .vdisplay = 800,
628 .vsync_start = 800 + 8,
629 .vsync_end = 800 + 8 + 2,
630 .vtotal = 800 + 8 + 2 + 6,
631 .vrefresh = 60,
632};
633
634static const struct panel_desc auo_g101evn010 = {
635 .modes = &auo_g101evn010_mode,
636 .num_modes = 1,
637 .bpc = 6,
638 .size = {
639 .width = 216,
640 .height = 135,
641 },
642 .bus_format = MEDIA_BUS_FMT_RGB666_1X18,
643};
644
621static const struct drm_display_mode auo_g104sn02_mode = { 645static const struct drm_display_mode auo_g104sn02_mode = {
622 .clock = 40000, 646 .clock = 40000,
623 .hdisplay = 800, 647 .hdisplay = 800,
@@ -2494,6 +2518,9 @@ static const struct of_device_id platform_of_match[] = {
2494 .compatible = "auo,g070vvn01", 2518 .compatible = "auo,g070vvn01",
2495 .data = &auo_g070vvn01, 2519 .data = &auo_g070vvn01,
2496 }, { 2520 }, {
2521 .compatible = "auo,g101evn010",
2522 .data = &auo_g101evn010,
2523 }, {
2497 .compatible = "auo,g104sn02", 2524 .compatible = "auo,g104sn02",
2498 .data = &auo_g104sn02, 2525 .data = &auo_g104sn02,
2499 }, { 2526 }, {
diff --git a/drivers/gpu/drm/pl111/pl111_vexpress.c b/drivers/gpu/drm/pl111/pl111_vexpress.c
index 5fa0441bb6df..38c938c9adda 100644
--- a/drivers/gpu/drm/pl111/pl111_vexpress.c
+++ b/drivers/gpu/drm/pl111/pl111_vexpress.c
@@ -55,6 +55,8 @@ int pl111_vexpress_clcd_init(struct device *dev,
55 } 55 }
56 } 56 }
57 57
58 of_node_put(root);
59
58 /* 60 /*
59 * If there is a coretile HDLCD and it has a driver, 61 * If there is a coretile HDLCD and it has a driver,
60 * do not mux the CLCD on the motherboard to the DVI. 62 * do not mux the CLCD on the motherboard to the DVI.
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
index 94f055186b95..f50a3b1864bb 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
@@ -21,6 +21,7 @@
21#include <drm/drm_atomic_helper.h> 21#include <drm/drm_atomic_helper.h>
22#include <drm/drm_crtc_helper.h> 22#include <drm/drm_crtc_helper.h>
23#include <drm/drm_fb_cma_helper.h> 23#include <drm/drm_fb_cma_helper.h>
24#include <drm/drm_fb_helper.h>
24#include <drm/drm_gem_cma_helper.h> 25#include <drm/drm_gem_cma_helper.h>
25 26
26#include "rcar_du_drv.h" 27#include "rcar_du_drv.h"
@@ -392,19 +393,11 @@ MODULE_DEVICE_TABLE(of, rcar_du_of_table);
392 * DRM operations 393 * DRM operations
393 */ 394 */
394 395
395static void rcar_du_lastclose(struct drm_device *dev)
396{
397 struct rcar_du_device *rcdu = dev->dev_private;
398
399 drm_fbdev_cma_restore_mode(rcdu->fbdev);
400}
401
402DEFINE_DRM_GEM_CMA_FOPS(rcar_du_fops); 396DEFINE_DRM_GEM_CMA_FOPS(rcar_du_fops);
403 397
404static struct drm_driver rcar_du_driver = { 398static struct drm_driver rcar_du_driver = {
405 .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME 399 .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME
406 | DRIVER_ATOMIC, 400 | DRIVER_ATOMIC,
407 .lastclose = rcar_du_lastclose,
408 .gem_free_object_unlocked = drm_gem_cma_free_object, 401 .gem_free_object_unlocked = drm_gem_cma_free_object,
409 .gem_vm_ops = &drm_gem_cma_vm_ops, 402 .gem_vm_ops = &drm_gem_cma_vm_ops,
410 .prime_handle_to_fd = drm_gem_prime_handle_to_fd, 403 .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
@@ -460,9 +453,6 @@ static int rcar_du_remove(struct platform_device *pdev)
460 453
461 drm_dev_unregister(ddev); 454 drm_dev_unregister(ddev);
462 455
463 if (rcdu->fbdev)
464 drm_fbdev_cma_fini(rcdu->fbdev);
465
466 drm_kms_helper_poll_fini(ddev); 456 drm_kms_helper_poll_fini(ddev);
467 drm_mode_config_cleanup(ddev); 457 drm_mode_config_cleanup(ddev);
468 458
@@ -522,6 +512,8 @@ static int rcar_du_probe(struct platform_device *pdev)
522 512
523 DRM_INFO("Device %s probed\n", dev_name(&pdev->dev)); 513 DRM_INFO("Device %s probed\n", dev_name(&pdev->dev));
524 514
515 drm_fbdev_generic_setup(ddev, 32);
516
525 return 0; 517 return 0;
526 518
527error: 519error:
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
index 9f5563296c5a..a68da79b424e 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
@@ -20,7 +20,6 @@
20struct clk; 20struct clk;
21struct device; 21struct device;
22struct drm_device; 22struct drm_device;
23struct drm_fbdev_cma;
24struct rcar_du_device; 23struct rcar_du_device;
25 24
26#define RCAR_DU_FEATURE_CRTC_IRQ_CLOCK BIT(0) /* Per-CRTC IRQ and clock */ 25#define RCAR_DU_FEATURE_CRTC_IRQ_CLOCK BIT(0) /* Per-CRTC IRQ and clock */
@@ -78,7 +77,6 @@ struct rcar_du_device {
78 void __iomem *mmio; 77 void __iomem *mmio;
79 78
80 struct drm_device *ddev; 79 struct drm_device *ddev;
81 struct drm_fbdev_cma *fbdev;
82 80
83 struct rcar_du_crtc crtcs[RCAR_DU_MAX_CRTCS]; 81 struct rcar_du_crtc crtcs[RCAR_DU_MAX_CRTCS];
84 unsigned int num_crtcs; 82 unsigned int num_crtcs;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index fe6f65c94eef..9c7007d45408 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -255,13 +255,6 @@ rcar_du_fb_create(struct drm_device *dev, struct drm_file *file_priv,
255 return drm_gem_fb_create(dev, file_priv, mode_cmd); 255 return drm_gem_fb_create(dev, file_priv, mode_cmd);
256} 256}
257 257
258static void rcar_du_output_poll_changed(struct drm_device *dev)
259{
260 struct rcar_du_device *rcdu = dev->dev_private;
261
262 drm_fbdev_cma_hotplug_event(rcdu->fbdev);
263}
264
265/* ----------------------------------------------------------------------------- 258/* -----------------------------------------------------------------------------
266 * Atomic Check and Update 259 * Atomic Check and Update
267 */ 260 */
@@ -308,7 +301,6 @@ static const struct drm_mode_config_helper_funcs rcar_du_mode_config_helper = {
308 301
309static const struct drm_mode_config_funcs rcar_du_mode_config_funcs = { 302static const struct drm_mode_config_funcs rcar_du_mode_config_funcs = {
310 .fb_create = rcar_du_fb_create, 303 .fb_create = rcar_du_fb_create,
311 .output_poll_changed = rcar_du_output_poll_changed,
312 .atomic_check = rcar_du_atomic_check, 304 .atomic_check = rcar_du_atomic_check,
313 .atomic_commit = drm_atomic_helper_commit, 305 .atomic_commit = drm_atomic_helper_commit,
314}; 306};
@@ -543,7 +535,6 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
543 535
544 struct drm_device *dev = rcdu->ddev; 536 struct drm_device *dev = rcdu->ddev;
545 struct drm_encoder *encoder; 537 struct drm_encoder *encoder;
546 struct drm_fbdev_cma *fbdev;
547 unsigned int dpad0_sources; 538 unsigned int dpad0_sources;
548 unsigned int num_encoders; 539 unsigned int num_encoders;
549 unsigned int num_groups; 540 unsigned int num_groups;
@@ -682,17 +673,5 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
682 673
683 drm_kms_helper_poll_init(dev); 674 drm_kms_helper_poll_init(dev);
684 675
685 if (dev->mode_config.num_connector) {
686 fbdev = drm_fbdev_cma_init(dev, 32,
687 dev->mode_config.num_connector);
688 if (IS_ERR(fbdev))
689 return PTR_ERR(fbdev);
690
691 rcdu->fbdev = fbdev;
692 } else {
693 dev_info(rcdu->dev,
694 "no connector found, disabling fbdev emulation\n");
695 }
696
697 return 0; 676 return 0;
698} 677}
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index ccdeae6299eb..9e4c375ccc96 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -410,6 +410,7 @@ static const struct of_device_id sun4i_drv_of_table[] = {
410 { .compatible = "allwinner,sun8i-v3s-display-engine" }, 410 { .compatible = "allwinner,sun8i-v3s-display-engine" },
411 { .compatible = "allwinner,sun9i-a80-display-engine" }, 411 { .compatible = "allwinner,sun9i-a80-display-engine" },
412 { .compatible = "allwinner,sun50i-a64-display-engine" }, 412 { .compatible = "allwinner,sun50i-a64-display-engine" },
413 { .compatible = "allwinner,sun50i-h6-display-engine" },
413 { } 414 { }
414}; 415};
415MODULE_DEVICE_TABLE(of, sun4i_drv_of_table); 416MODULE_DEVICE_TABLE(of, sun4i_drv_of_table);
diff --git a/drivers/gpu/drm/tinydrm/repaper.c b/drivers/gpu/drm/tinydrm/repaper.c
index 07f45a008a0f..54d6fe0f37ce 100644
--- a/drivers/gpu/drm/tinydrm/repaper.c
+++ b/drivers/gpu/drm/tinydrm/repaper.c
@@ -108,12 +108,11 @@ static int repaper_spi_transfer(struct spi_device *spi, u8 header,
108 108
109 /* Stack allocated tx? */ 109 /* Stack allocated tx? */
110 if (tx && len <= 32) { 110 if (tx && len <= 32) {
111 txbuf = kmalloc(len, GFP_KERNEL); 111 txbuf = kmemdup(tx, len, GFP_KERNEL);
112 if (!txbuf) { 112 if (!txbuf) {
113 ret = -ENOMEM; 113 ret = -ENOMEM;
114 goto out_free; 114 goto out_free;
115 } 115 }
116 memcpy(txbuf, tx, len);
117 } 116 }
118 117
119 if (rx) { 118 if (rx) {
diff --git a/drivers/gpu/drm/v3d/v3d_bo.c b/drivers/gpu/drm/v3d/v3d_bo.c
index 54d96518a131..a08766d39eab 100644
--- a/drivers/gpu/drm/v3d/v3d_bo.c
+++ b/drivers/gpu/drm/v3d/v3d_bo.c
@@ -293,6 +293,7 @@ v3d_prime_import_sg_table(struct drm_device *dev,
293 bo->resv = attach->dmabuf->resv; 293 bo->resv = attach->dmabuf->resv;
294 294
295 bo->sgt = sgt; 295 bo->sgt = sgt;
296 obj->import_attach = attach;
296 v3d_bo_get_pages(bo); 297 v3d_bo_get_pages(bo);
297 298
298 v3d_mmu_insert_ptes(bo); 299 v3d_mmu_insert_ptes(bo);
diff --git a/drivers/gpu/drm/v3d/v3d_drv.c b/drivers/gpu/drm/v3d/v3d_drv.c
index 2a85fa68ffea..f0afcec72c34 100644
--- a/drivers/gpu/drm/v3d/v3d_drv.c
+++ b/drivers/gpu/drm/v3d/v3d_drv.c
@@ -112,10 +112,15 @@ static int v3d_get_param_ioctl(struct drm_device *dev, void *data,
112 return 0; 112 return 0;
113 } 113 }
114 114
115 /* Any params that aren't just register reads would go here. */
116 115
117 DRM_DEBUG("Unknown parameter %d\n", args->param); 116 switch (args->param) {
118 return -EINVAL; 117 case DRM_V3D_PARAM_SUPPORTS_TFU:
118 args->value = 1;
119 return 0;
120 default:
121 DRM_DEBUG("Unknown parameter %d\n", args->param);
122 return -EINVAL;
123 }
119} 124}
120 125
121static int 126static int
@@ -170,7 +175,8 @@ static const struct file_operations v3d_drm_fops = {
170/* DRM_AUTH is required on SUBMIT_CL for now, while we don't have GMP 175/* DRM_AUTH is required on SUBMIT_CL for now, while we don't have GMP
171 * protection between clients. Note that render nodes would be be 176 * protection between clients. Note that render nodes would be be
172 * able to submit CLs that could access BOs from clients authenticated 177 * able to submit CLs that could access BOs from clients authenticated
173 * with the master node. 178 * with the master node. The TFU doesn't use the GMP, so it would
179 * need to stay DRM_AUTH until we do buffer size/offset validation.
174 */ 180 */
175static const struct drm_ioctl_desc v3d_drm_ioctls[] = { 181static const struct drm_ioctl_desc v3d_drm_ioctls[] = {
176 DRM_IOCTL_DEF_DRV(V3D_SUBMIT_CL, v3d_submit_cl_ioctl, DRM_RENDER_ALLOW | DRM_AUTH), 182 DRM_IOCTL_DEF_DRV(V3D_SUBMIT_CL, v3d_submit_cl_ioctl, DRM_RENDER_ALLOW | DRM_AUTH),
@@ -179,6 +185,7 @@ static const struct drm_ioctl_desc v3d_drm_ioctls[] = {
179 DRM_IOCTL_DEF_DRV(V3D_MMAP_BO, v3d_mmap_bo_ioctl, DRM_RENDER_ALLOW), 185 DRM_IOCTL_DEF_DRV(V3D_MMAP_BO, v3d_mmap_bo_ioctl, DRM_RENDER_ALLOW),
180 DRM_IOCTL_DEF_DRV(V3D_GET_PARAM, v3d_get_param_ioctl, DRM_RENDER_ALLOW), 186 DRM_IOCTL_DEF_DRV(V3D_GET_PARAM, v3d_get_param_ioctl, DRM_RENDER_ALLOW),
181 DRM_IOCTL_DEF_DRV(V3D_GET_BO_OFFSET, v3d_get_bo_offset_ioctl, DRM_RENDER_ALLOW), 187 DRM_IOCTL_DEF_DRV(V3D_GET_BO_OFFSET, v3d_get_bo_offset_ioctl, DRM_RENDER_ALLOW),
188 DRM_IOCTL_DEF_DRV(V3D_SUBMIT_TFU, v3d_submit_tfu_ioctl, DRM_RENDER_ALLOW | DRM_AUTH),
182}; 189};
183 190
184static const struct vm_operations_struct v3d_vm_ops = { 191static const struct vm_operations_struct v3d_vm_ops = {
diff --git a/drivers/gpu/drm/v3d/v3d_drv.h b/drivers/gpu/drm/v3d/v3d_drv.h
index cbe5be0c47eb..dcb772a19191 100644
--- a/drivers/gpu/drm/v3d/v3d_drv.h
+++ b/drivers/gpu/drm/v3d/v3d_drv.h
@@ -7,19 +7,18 @@
7#include <drm/drm_encoder.h> 7#include <drm/drm_encoder.h>
8#include <drm/drm_gem.h> 8#include <drm/drm_gem.h>
9#include <drm/gpu_scheduler.h> 9#include <drm/gpu_scheduler.h>
10#include "uapi/drm/v3d_drm.h"
10 11
11#define GMP_GRANULARITY (128 * 1024) 12#define GMP_GRANULARITY (128 * 1024)
12 13
13/* Enum for each of the V3D queues. We maintain various queue 14/* Enum for each of the V3D queues. */
14 * tracking as an array because at some point we'll want to support
15 * the TFU (texture formatting unit) as another queue.
16 */
17enum v3d_queue { 15enum v3d_queue {
18 V3D_BIN, 16 V3D_BIN,
19 V3D_RENDER, 17 V3D_RENDER,
18 V3D_TFU,
20}; 19};
21 20
22#define V3D_MAX_QUEUES (V3D_RENDER + 1) 21#define V3D_MAX_QUEUES (V3D_TFU + 1)
23 22
24struct v3d_queue_state { 23struct v3d_queue_state {
25 struct drm_gpu_scheduler sched; 24 struct drm_gpu_scheduler sched;
@@ -68,6 +67,7 @@ struct v3d_dev {
68 67
69 struct v3d_exec_info *bin_job; 68 struct v3d_exec_info *bin_job;
70 struct v3d_exec_info *render_job; 69 struct v3d_exec_info *render_job;
70 struct v3d_tfu_job *tfu_job;
71 71
72 struct v3d_queue_state queue[V3D_MAX_QUEUES]; 72 struct v3d_queue_state queue[V3D_MAX_QUEUES];
73 73
@@ -218,6 +218,25 @@ struct v3d_exec_info {
218 u32 qma, qms, qts; 218 u32 qma, qms, qts;
219}; 219};
220 220
221struct v3d_tfu_job {
222 struct drm_sched_job base;
223
224 struct drm_v3d_submit_tfu args;
225
226 /* An optional fence userspace can pass in for the job to depend on. */
227 struct dma_fence *in_fence;
228
229 /* v3d fence to be signaled by IRQ handler when the job is complete. */
230 struct dma_fence *done_fence;
231
232 struct v3d_dev *v3d;
233
234 struct kref refcount;
235
236 /* This is the array of BOs that were looked up at the start of exec. */
237 struct v3d_bo *bo[4];
238};
239
221/** 240/**
222 * _wait_for - magic (register) wait macro 241 * _wait_for - magic (register) wait macro
223 * 242 *
@@ -281,9 +300,12 @@ int v3d_gem_init(struct drm_device *dev);
281void v3d_gem_destroy(struct drm_device *dev); 300void v3d_gem_destroy(struct drm_device *dev);
282int v3d_submit_cl_ioctl(struct drm_device *dev, void *data, 301int v3d_submit_cl_ioctl(struct drm_device *dev, void *data,
283 struct drm_file *file_priv); 302 struct drm_file *file_priv);
303int v3d_submit_tfu_ioctl(struct drm_device *dev, void *data,
304 struct drm_file *file_priv);
284int v3d_wait_bo_ioctl(struct drm_device *dev, void *data, 305int v3d_wait_bo_ioctl(struct drm_device *dev, void *data,
285 struct drm_file *file_priv); 306 struct drm_file *file_priv);
286void v3d_exec_put(struct v3d_exec_info *exec); 307void v3d_exec_put(struct v3d_exec_info *exec);
308void v3d_tfu_job_put(struct v3d_tfu_job *exec);
287void v3d_reset(struct v3d_dev *v3d); 309void v3d_reset(struct v3d_dev *v3d);
288void v3d_invalidate_caches(struct v3d_dev *v3d); 310void v3d_invalidate_caches(struct v3d_dev *v3d);
289void v3d_flush_caches(struct v3d_dev *v3d); 311void v3d_flush_caches(struct v3d_dev *v3d);
diff --git a/drivers/gpu/drm/v3d/v3d_fence.c b/drivers/gpu/drm/v3d/v3d_fence.c
index 50bfcf9a8a1a..b0a2a1ae2eb1 100644
--- a/drivers/gpu/drm/v3d/v3d_fence.c
+++ b/drivers/gpu/drm/v3d/v3d_fence.c
@@ -29,10 +29,16 @@ static const char *v3d_fence_get_timeline_name(struct dma_fence *fence)
29{ 29{
30 struct v3d_fence *f = to_v3d_fence(fence); 30 struct v3d_fence *f = to_v3d_fence(fence);
31 31
32 if (f->queue == V3D_BIN) 32 switch (f->queue) {
33 case V3D_BIN:
33 return "v3d-bin"; 34 return "v3d-bin";
34 else 35 case V3D_RENDER:
35 return "v3d-render"; 36 return "v3d-render";
37 case V3D_TFU:
38 return "v3d-tfu";
39 default:
40 return NULL;
41 }
36} 42}
37 43
38const struct dma_fence_ops v3d_fence_ops = { 44const struct dma_fence_ops v3d_fence_ops = {
diff --git a/drivers/gpu/drm/v3d/v3d_gem.c b/drivers/gpu/drm/v3d/v3d_gem.c
index 1e8947c7d954..05ca6319065e 100644
--- a/drivers/gpu/drm/v3d/v3d_gem.c
+++ b/drivers/gpu/drm/v3d/v3d_gem.c
@@ -207,26 +207,26 @@ v3d_flush_caches(struct v3d_dev *v3d)
207} 207}
208 208
209static void 209static void
210v3d_attach_object_fences(struct v3d_exec_info *exec) 210v3d_attach_object_fences(struct v3d_bo **bos, int bo_count,
211 struct dma_fence *fence)
211{ 212{
212 struct dma_fence *out_fence = exec->render_done_fence;
213 int i; 213 int i;
214 214
215 for (i = 0; i < exec->bo_count; i++) { 215 for (i = 0; i < bo_count; i++) {
216 /* XXX: Use shared fences for read-only objects. */ 216 /* XXX: Use shared fences for read-only objects. */
217 reservation_object_add_excl_fence(exec->bo[i]->resv, out_fence); 217 reservation_object_add_excl_fence(bos[i]->resv, fence);
218 } 218 }
219} 219}
220 220
221static void 221static void
222v3d_unlock_bo_reservations(struct drm_device *dev, 222v3d_unlock_bo_reservations(struct v3d_bo **bos,
223 struct v3d_exec_info *exec, 223 int bo_count,
224 struct ww_acquire_ctx *acquire_ctx) 224 struct ww_acquire_ctx *acquire_ctx)
225{ 225{
226 int i; 226 int i;
227 227
228 for (i = 0; i < exec->bo_count; i++) 228 for (i = 0; i < bo_count; i++)
229 ww_mutex_unlock(&exec->bo[i]->resv->lock); 229 ww_mutex_unlock(&bos[i]->resv->lock);
230 230
231 ww_acquire_fini(acquire_ctx); 231 ww_acquire_fini(acquire_ctx);
232} 232}
@@ -239,8 +239,8 @@ v3d_unlock_bo_reservations(struct drm_device *dev,
239 * to v3d, so we don't attach dma-buf fences to them. 239 * to v3d, so we don't attach dma-buf fences to them.
240 */ 240 */
241static int 241static int
242v3d_lock_bo_reservations(struct drm_device *dev, 242v3d_lock_bo_reservations(struct v3d_bo **bos,
243 struct v3d_exec_info *exec, 243 int bo_count,
244 struct ww_acquire_ctx *acquire_ctx) 244 struct ww_acquire_ctx *acquire_ctx)
245{ 245{
246 int contended_lock = -1; 246 int contended_lock = -1;
@@ -250,7 +250,7 @@ v3d_lock_bo_reservations(struct drm_device *dev,
250 250
251retry: 251retry:
252 if (contended_lock != -1) { 252 if (contended_lock != -1) {
253 struct v3d_bo *bo = exec->bo[contended_lock]; 253 struct v3d_bo *bo = bos[contended_lock];
254 254
255 ret = ww_mutex_lock_slow_interruptible(&bo->resv->lock, 255 ret = ww_mutex_lock_slow_interruptible(&bo->resv->lock,
256 acquire_ctx); 256 acquire_ctx);
@@ -260,20 +260,20 @@ retry:
260 } 260 }
261 } 261 }
262 262
263 for (i = 0; i < exec->bo_count; i++) { 263 for (i = 0; i < bo_count; i++) {
264 if (i == contended_lock) 264 if (i == contended_lock)
265 continue; 265 continue;
266 266
267 ret = ww_mutex_lock_interruptible(&exec->bo[i]->resv->lock, 267 ret = ww_mutex_lock_interruptible(&bos[i]->resv->lock,
268 acquire_ctx); 268 acquire_ctx);
269 if (ret) { 269 if (ret) {
270 int j; 270 int j;
271 271
272 for (j = 0; j < i; j++) 272 for (j = 0; j < i; j++)
273 ww_mutex_unlock(&exec->bo[j]->resv->lock); 273 ww_mutex_unlock(&bos[j]->resv->lock);
274 274
275 if (contended_lock != -1 && contended_lock >= i) { 275 if (contended_lock != -1 && contended_lock >= i) {
276 struct v3d_bo *bo = exec->bo[contended_lock]; 276 struct v3d_bo *bo = bos[contended_lock];
277 277
278 ww_mutex_unlock(&bo->resv->lock); 278 ww_mutex_unlock(&bo->resv->lock);
279 } 279 }
@@ -293,10 +293,11 @@ retry:
293 /* Reserve space for our shared (read-only) fence references, 293 /* Reserve space for our shared (read-only) fence references,
294 * before we commit the CL to the hardware. 294 * before we commit the CL to the hardware.
295 */ 295 */
296 for (i = 0; i < exec->bo_count; i++) { 296 for (i = 0; i < bo_count; i++) {
297 ret = reservation_object_reserve_shared(exec->bo[i]->resv, 1); 297 ret = reservation_object_reserve_shared(bos[i]->resv, 1);
298 if (ret) { 298 if (ret) {
299 v3d_unlock_bo_reservations(dev, exec, acquire_ctx); 299 v3d_unlock_bo_reservations(bos, bo_count,
300 acquire_ctx);
300 return ret; 301 return ret;
301 } 302 }
302 } 303 }
@@ -419,6 +420,33 @@ void v3d_exec_put(struct v3d_exec_info *exec)
419 kref_put(&exec->refcount, v3d_exec_cleanup); 420 kref_put(&exec->refcount, v3d_exec_cleanup);
420} 421}
421 422
423static void
424v3d_tfu_job_cleanup(struct kref *ref)
425{
426 struct v3d_tfu_job *job = container_of(ref, struct v3d_tfu_job,
427 refcount);
428 struct v3d_dev *v3d = job->v3d;
429 unsigned int i;
430
431 dma_fence_put(job->in_fence);
432 dma_fence_put(job->done_fence);
433
434 for (i = 0; i < ARRAY_SIZE(job->bo); i++) {
435 if (job->bo[i])
436 drm_gem_object_put_unlocked(&job->bo[i]->base);
437 }
438
439 pm_runtime_mark_last_busy(v3d->dev);
440 pm_runtime_put_autosuspend(v3d->dev);
441
442 kfree(job);
443}
444
445void v3d_tfu_job_put(struct v3d_tfu_job *job)
446{
447 kref_put(&job->refcount, v3d_tfu_job_cleanup);
448}
449
422int 450int
423v3d_wait_bo_ioctl(struct drm_device *dev, void *data, 451v3d_wait_bo_ioctl(struct drm_device *dev, void *data,
424 struct drm_file *file_priv) 452 struct drm_file *file_priv)
@@ -493,6 +521,8 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data,
493 struct drm_syncobj *sync_out; 521 struct drm_syncobj *sync_out;
494 int ret = 0; 522 int ret = 0;
495 523
524 trace_v3d_submit_cl_ioctl(&v3d->drm, args->rcl_start, args->rcl_end);
525
496 if (args->pad != 0) { 526 if (args->pad != 0) {
497 DRM_INFO("pad must be zero: %d\n", args->pad); 527 DRM_INFO("pad must be zero: %d\n", args->pad);
498 return -EINVAL; 528 return -EINVAL;
@@ -536,7 +566,8 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data,
536 if (ret) 566 if (ret)
537 goto fail; 567 goto fail;
538 568
539 ret = v3d_lock_bo_reservations(dev, exec, &acquire_ctx); 569 ret = v3d_lock_bo_reservations(exec->bo, exec->bo_count,
570 &acquire_ctx);
540 if (ret) 571 if (ret)
541 goto fail; 572 goto fail;
542 573
@@ -570,15 +601,15 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data,
570 &v3d_priv->sched_entity[V3D_RENDER]); 601 &v3d_priv->sched_entity[V3D_RENDER]);
571 mutex_unlock(&v3d->sched_lock); 602 mutex_unlock(&v3d->sched_lock);
572 603
573 v3d_attach_object_fences(exec); 604 v3d_attach_object_fences(exec->bo, exec->bo_count,
605 exec->render_done_fence);
574 606
575 v3d_unlock_bo_reservations(dev, exec, &acquire_ctx); 607 v3d_unlock_bo_reservations(exec->bo, exec->bo_count, &acquire_ctx);
576 608
577 /* Update the return sync object for the */ 609 /* Update the return sync object for the */
578 sync_out = drm_syncobj_find(file_priv, args->out_sync); 610 sync_out = drm_syncobj_find(file_priv, args->out_sync);
579 if (sync_out) { 611 if (sync_out) {
580 drm_syncobj_replace_fence(sync_out, 0, 612 drm_syncobj_replace_fence(sync_out, exec->render_done_fence);
581 exec->render_done_fence);
582 drm_syncobj_put(sync_out); 613 drm_syncobj_put(sync_out);
583 } 614 }
584 615
@@ -588,13 +619,121 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data,
588 619
589fail_unreserve: 620fail_unreserve:
590 mutex_unlock(&v3d->sched_lock); 621 mutex_unlock(&v3d->sched_lock);
591 v3d_unlock_bo_reservations(dev, exec, &acquire_ctx); 622 v3d_unlock_bo_reservations(exec->bo, exec->bo_count, &acquire_ctx);
592fail: 623fail:
593 v3d_exec_put(exec); 624 v3d_exec_put(exec);
594 625
595 return ret; 626 return ret;
596} 627}
597 628
629/**
630 * v3d_submit_tfu_ioctl() - Submits a TFU (texture formatting) job to the V3D.
631 * @dev: DRM device
632 * @data: ioctl argument
633 * @file_priv: DRM file for this fd
634 *
635 * Userspace provides the register setup for the TFU, which we don't
636 * need to validate since the TFU is behind the MMU.
637 */
638int
639v3d_submit_tfu_ioctl(struct drm_device *dev, void *data,
640 struct drm_file *file_priv)
641{
642 struct v3d_dev *v3d = to_v3d_dev(dev);
643 struct v3d_file_priv *v3d_priv = file_priv->driver_priv;
644 struct drm_v3d_submit_tfu *args = data;
645 struct v3d_tfu_job *job;
646 struct ww_acquire_ctx acquire_ctx;
647 struct drm_syncobj *sync_out;
648 struct dma_fence *sched_done_fence;
649 int ret = 0;
650 int bo_count;
651
652 trace_v3d_submit_tfu_ioctl(&v3d->drm, args->iia);
653
654 job = kcalloc(1, sizeof(*job), GFP_KERNEL);
655 if (!job)
656 return -ENOMEM;
657
658 ret = pm_runtime_get_sync(v3d->dev);
659 if (ret < 0) {
660 kfree(job);
661 return ret;
662 }
663
664 kref_init(&job->refcount);
665
666 ret = drm_syncobj_find_fence(file_priv, args->in_sync,
667 0, 0, &job->in_fence);
668 if (ret == -EINVAL)
669 goto fail;
670
671 job->args = *args;
672 job->v3d = v3d;
673
674 spin_lock(&file_priv->table_lock);
675 for (bo_count = 0; bo_count < ARRAY_SIZE(job->bo); bo_count++) {
676 struct drm_gem_object *bo;
677
678 if (!args->bo_handles[bo_count])
679 break;
680
681 bo = idr_find(&file_priv->object_idr,
682 args->bo_handles[bo_count]);
683 if (!bo) {
684 DRM_DEBUG("Failed to look up GEM BO %d: %d\n",
685 bo_count, args->bo_handles[bo_count]);
686 ret = -ENOENT;
687 spin_unlock(&file_priv->table_lock);
688 goto fail;
689 }
690 drm_gem_object_get(bo);
691 job->bo[bo_count] = to_v3d_bo(bo);
692 }
693 spin_unlock(&file_priv->table_lock);
694
695 ret = v3d_lock_bo_reservations(job->bo, bo_count, &acquire_ctx);
696 if (ret)
697 goto fail;
698
699 mutex_lock(&v3d->sched_lock);
700 ret = drm_sched_job_init(&job->base,
701 &v3d_priv->sched_entity[V3D_TFU],
702 v3d_priv);
703 if (ret)
704 goto fail_unreserve;
705
706 sched_done_fence = dma_fence_get(&job->base.s_fence->finished);
707
708 kref_get(&job->refcount); /* put by scheduler job completion */
709 drm_sched_entity_push_job(&job->base, &v3d_priv->sched_entity[V3D_TFU]);
710 mutex_unlock(&v3d->sched_lock);
711
712 v3d_attach_object_fences(job->bo, bo_count, sched_done_fence);
713
714 v3d_unlock_bo_reservations(job->bo, bo_count, &acquire_ctx);
715
716 /* Update the return sync object */
717 sync_out = drm_syncobj_find(file_priv, args->out_sync);
718 if (sync_out) {
719 drm_syncobj_replace_fence(sync_out, sched_done_fence);
720 drm_syncobj_put(sync_out);
721 }
722 dma_fence_put(sched_done_fence);
723
724 v3d_tfu_job_put(job);
725
726 return 0;
727
728fail_unreserve:
729 mutex_unlock(&v3d->sched_lock);
730 v3d_unlock_bo_reservations(job->bo, bo_count, &acquire_ctx);
731fail:
732 v3d_tfu_job_put(job);
733
734 return ret;
735}
736
598int 737int
599v3d_gem_init(struct drm_device *dev) 738v3d_gem_init(struct drm_device *dev)
600{ 739{
diff --git a/drivers/gpu/drm/v3d/v3d_irq.c b/drivers/gpu/drm/v3d/v3d_irq.c
index e07514eb11b5..69338da70ddc 100644
--- a/drivers/gpu/drm/v3d/v3d_irq.c
+++ b/drivers/gpu/drm/v3d/v3d_irq.c
@@ -4,8 +4,8 @@
4/** 4/**
5 * DOC: Interrupt management for the V3D engine 5 * DOC: Interrupt management for the V3D engine
6 * 6 *
7 * When we take a binning or rendering flush done interrupt, we need 7 * When we take a bin, render, or TFU done interrupt, we need to
8 * to signal the fence for that job so that the scheduler can queue up 8 * signal the fence for that job so that the scheduler can queue up
9 * the next one and unblock any waiters. 9 * the next one and unblock any waiters.
10 * 10 *
11 * When we take the binner out of memory interrupt, we need to 11 * When we take the binner out of memory interrupt, we need to
@@ -15,6 +15,7 @@
15 15
16#include "v3d_drv.h" 16#include "v3d_drv.h"
17#include "v3d_regs.h" 17#include "v3d_regs.h"
18#include "v3d_trace.h"
18 19
19#define V3D_CORE_IRQS ((u32)(V3D_INT_OUTOMEM | \ 20#define V3D_CORE_IRQS ((u32)(V3D_INT_OUTOMEM | \
20 V3D_INT_FLDONE | \ 21 V3D_INT_FLDONE | \
@@ -23,7 +24,8 @@
23 24
24#define V3D_HUB_IRQS ((u32)(V3D_HUB_INT_MMU_WRV | \ 25#define V3D_HUB_IRQS ((u32)(V3D_HUB_INT_MMU_WRV | \
25 V3D_HUB_INT_MMU_PTI | \ 26 V3D_HUB_INT_MMU_PTI | \
26 V3D_HUB_INT_MMU_CAP)) 27 V3D_HUB_INT_MMU_CAP | \
28 V3D_HUB_INT_TFUC))
27 29
28static void 30static void
29v3d_overflow_mem_work(struct work_struct *work) 31v3d_overflow_mem_work(struct work_struct *work)
@@ -87,12 +89,20 @@ v3d_irq(int irq, void *arg)
87 } 89 }
88 90
89 if (intsts & V3D_INT_FLDONE) { 91 if (intsts & V3D_INT_FLDONE) {
90 dma_fence_signal(v3d->bin_job->bin.done_fence); 92 struct v3d_fence *fence =
93 to_v3d_fence(v3d->bin_job->bin.done_fence);
94
95 trace_v3d_bcl_irq(&v3d->drm, fence->seqno);
96 dma_fence_signal(&fence->base);
91 status = IRQ_HANDLED; 97 status = IRQ_HANDLED;
92 } 98 }
93 99
94 if (intsts & V3D_INT_FRDONE) { 100 if (intsts & V3D_INT_FRDONE) {
95 dma_fence_signal(v3d->render_job->render.done_fence); 101 struct v3d_fence *fence =
102 to_v3d_fence(v3d->render_job->render.done_fence);
103
104 trace_v3d_rcl_irq(&v3d->drm, fence->seqno);
105 dma_fence_signal(&fence->base);
96 status = IRQ_HANDLED; 106 status = IRQ_HANDLED;
97 } 107 }
98 108
@@ -117,6 +127,15 @@ v3d_hub_irq(int irq, void *arg)
117 /* Acknowledge the interrupts we're handling here. */ 127 /* Acknowledge the interrupts we're handling here. */
118 V3D_WRITE(V3D_HUB_INT_CLR, intsts); 128 V3D_WRITE(V3D_HUB_INT_CLR, intsts);
119 129
130 if (intsts & V3D_HUB_INT_TFUC) {
131 struct v3d_fence *fence =
132 to_v3d_fence(v3d->tfu_job->done_fence);
133
134 trace_v3d_tfu_irq(&v3d->drm, fence->seqno);
135 dma_fence_signal(&fence->base);
136 status = IRQ_HANDLED;
137 }
138
120 if (intsts & (V3D_HUB_INT_MMU_WRV | 139 if (intsts & (V3D_HUB_INT_MMU_WRV |
121 V3D_HUB_INT_MMU_PTI | 140 V3D_HUB_INT_MMU_PTI |
122 V3D_HUB_INT_MMU_CAP)) { 141 V3D_HUB_INT_MMU_CAP)) {
diff --git a/drivers/gpu/drm/v3d/v3d_regs.h b/drivers/gpu/drm/v3d/v3d_regs.h
index c3a5e4e44f73..6ccdee9d47bd 100644
--- a/drivers/gpu/drm/v3d/v3d_regs.h
+++ b/drivers/gpu/drm/v3d/v3d_regs.h
@@ -86,6 +86,55 @@
86# define V3D_TOP_GR_BRIDGE_SW_INIT_1 0x0000c 86# define V3D_TOP_GR_BRIDGE_SW_INIT_1 0x0000c
87# define V3D_TOP_GR_BRIDGE_SW_INIT_1_V3D_CLK_108_SW_INIT BIT(0) 87# define V3D_TOP_GR_BRIDGE_SW_INIT_1_V3D_CLK_108_SW_INIT BIT(0)
88 88
89#define V3D_TFU_CS 0x00400
90/* Stops current job, empties input fifo. */
91# define V3D_TFU_CS_TFURST BIT(31)
92# define V3D_TFU_CS_CVTCT_MASK V3D_MASK(23, 16)
93# define V3D_TFU_CS_CVTCT_SHIFT 16
94# define V3D_TFU_CS_NFREE_MASK V3D_MASK(13, 8)
95# define V3D_TFU_CS_NFREE_SHIFT 8
96# define V3D_TFU_CS_BUSY BIT(0)
97
98#define V3D_TFU_SU 0x00404
99/* Interrupt when FINTTHR input slots are free (0 = disabled) */
100# define V3D_TFU_SU_FINTTHR_MASK V3D_MASK(13, 8)
101# define V3D_TFU_SU_FINTTHR_SHIFT 8
102/* Skips resetting the CRC at the start of CRC generation. */
103# define V3D_TFU_SU_CRCCHAIN BIT(4)
104/* skips writes, computes CRC of the image. miplevels must be 0. */
105# define V3D_TFU_SU_CRC BIT(3)
106# define V3D_TFU_SU_THROTTLE_MASK V3D_MASK(1, 0)
107# define V3D_TFU_SU_THROTTLE_SHIFT 0
108
109#define V3D_TFU_ICFG 0x00408
110/* Interrupt when the conversion is complete. */
111# define V3D_TFU_ICFG_IOC BIT(0)
112
113/* Input Image Address */
114#define V3D_TFU_IIA 0x0040c
115/* Input Chroma Address */
116#define V3D_TFU_ICA 0x00410
117/* Input Image Stride */
118#define V3D_TFU_IIS 0x00414
119/* Input Image U-Plane Address */
120#define V3D_TFU_IUA 0x00418
121/* Output Image Address */
122#define V3D_TFU_IOA 0x0041c
123/* Image Output Size */
124#define V3D_TFU_IOS 0x00420
125/* TFU YUV Coefficient 0 */
126#define V3D_TFU_COEF0 0x00424
127/* Use these regs instead of the defaults. */
128# define V3D_TFU_COEF0_USECOEF BIT(31)
129/* TFU YUV Coefficient 1 */
130#define V3D_TFU_COEF1 0x00428
131/* TFU YUV Coefficient 2 */
132#define V3D_TFU_COEF2 0x0042c
133/* TFU YUV Coefficient 3 */
134#define V3D_TFU_COEF3 0x00430
135
136#define V3D_TFU_CRC 0x00434
137
89/* Per-MMU registers. */ 138/* Per-MMU registers. */
90 139
91#define V3D_MMUC_CONTROL 0x01000 140#define V3D_MMUC_CONTROL 0x01000
diff --git a/drivers/gpu/drm/v3d/v3d_sched.c b/drivers/gpu/drm/v3d/v3d_sched.c
index c66d0ce21435..f7508e907536 100644
--- a/drivers/gpu/drm/v3d/v3d_sched.c
+++ b/drivers/gpu/drm/v3d/v3d_sched.c
@@ -30,6 +30,12 @@ to_v3d_job(struct drm_sched_job *sched_job)
30 return container_of(sched_job, struct v3d_job, base); 30 return container_of(sched_job, struct v3d_job, base);
31} 31}
32 32
33static struct v3d_tfu_job *
34to_tfu_job(struct drm_sched_job *sched_job)
35{
36 return container_of(sched_job, struct v3d_tfu_job, base);
37}
38
33static void 39static void
34v3d_job_free(struct drm_sched_job *sched_job) 40v3d_job_free(struct drm_sched_job *sched_job)
35{ 41{
@@ -40,6 +46,16 @@ v3d_job_free(struct drm_sched_job *sched_job)
40 v3d_exec_put(job->exec); 46 v3d_exec_put(job->exec);
41} 47}
42 48
49static void
50v3d_tfu_job_free(struct drm_sched_job *sched_job)
51{
52 struct v3d_tfu_job *job = to_tfu_job(sched_job);
53
54 drm_sched_job_cleanup(sched_job);
55
56 v3d_tfu_job_put(job);
57}
58
43/** 59/**
44 * Returns the fences that the bin or render job depends on, one by one. 60 * Returns the fences that the bin or render job depends on, one by one.
45 * v3d_job_run() won't be called until all of them have been signaled. 61 * v3d_job_run() won't be called until all of them have been signaled.
@@ -78,6 +94,27 @@ v3d_job_dependency(struct drm_sched_job *sched_job,
78 return fence; 94 return fence;
79} 95}
80 96
97/**
98 * Returns the fences that the TFU job depends on, one by one.
99 * v3d_tfu_job_run() won't be called until all of them have been
100 * signaled.
101 */
102static struct dma_fence *
103v3d_tfu_job_dependency(struct drm_sched_job *sched_job,
104 struct drm_sched_entity *s_entity)
105{
106 struct v3d_tfu_job *job = to_tfu_job(sched_job);
107 struct dma_fence *fence;
108
109 fence = job->in_fence;
110 if (fence) {
111 job->in_fence = NULL;
112 return fence;
113 }
114
115 return NULL;
116}
117
81static struct dma_fence *v3d_job_run(struct drm_sched_job *sched_job) 118static struct dma_fence *v3d_job_run(struct drm_sched_job *sched_job)
82{ 119{
83 struct v3d_job *job = to_v3d_job(sched_job); 120 struct v3d_job *job = to_v3d_job(sched_job);
@@ -149,28 +186,47 @@ static struct dma_fence *v3d_job_run(struct drm_sched_job *sched_job)
149 return fence; 186 return fence;
150} 187}
151 188
152static void 189static struct dma_fence *
153v3d_job_timedout(struct drm_sched_job *sched_job) 190v3d_tfu_job_run(struct drm_sched_job *sched_job)
154{ 191{
155 struct v3d_job *job = to_v3d_job(sched_job); 192 struct v3d_tfu_job *job = to_tfu_job(sched_job);
156 struct v3d_exec_info *exec = job->exec; 193 struct v3d_dev *v3d = job->v3d;
157 struct v3d_dev *v3d = exec->v3d; 194 struct drm_device *dev = &v3d->drm;
158 enum v3d_queue job_q = job == &exec->bin ? V3D_BIN : V3D_RENDER; 195 struct dma_fence *fence;
159 enum v3d_queue q;
160 u32 ctca = V3D_CORE_READ(0, V3D_CLE_CTNCA(job_q));
161 u32 ctra = V3D_CORE_READ(0, V3D_CLE_CTNRA(job_q));
162 196
163 /* If the current address or return address have changed, then 197 fence = v3d_fence_create(v3d, V3D_TFU);
164 * the GPU has probably made progress and we should delay the 198 if (IS_ERR(fence))
165 * reset. This could fail if the GPU got in an infinite loop 199 return NULL;
166 * in the CL, but that is pretty unlikely outside of an i-g-t 200
167 * testcase. 201 v3d->tfu_job = job;
168 */ 202 if (job->done_fence)
169 if (job->timedout_ctca != ctca || job->timedout_ctra != ctra) { 203 dma_fence_put(job->done_fence);
170 job->timedout_ctca = ctca; 204 job->done_fence = dma_fence_get(fence);
171 job->timedout_ctra = ctra; 205
172 return; 206 trace_v3d_submit_tfu(dev, to_v3d_fence(fence)->seqno);
207
208 V3D_WRITE(V3D_TFU_IIA, job->args.iia);
209 V3D_WRITE(V3D_TFU_IIS, job->args.iis);
210 V3D_WRITE(V3D_TFU_ICA, job->args.ica);
211 V3D_WRITE(V3D_TFU_IUA, job->args.iua);
212 V3D_WRITE(V3D_TFU_IOA, job->args.ioa);
213 V3D_WRITE(V3D_TFU_IOS, job->args.ios);
214 V3D_WRITE(V3D_TFU_COEF0, job->args.coef[0]);
215 if (job->args.coef[0] & V3D_TFU_COEF0_USECOEF) {
216 V3D_WRITE(V3D_TFU_COEF1, job->args.coef[1]);
217 V3D_WRITE(V3D_TFU_COEF2, job->args.coef[2]);
218 V3D_WRITE(V3D_TFU_COEF3, job->args.coef[3]);
173 } 219 }
220 /* ICFG kicks off the job. */
221 V3D_WRITE(V3D_TFU_ICFG, job->args.icfg | V3D_TFU_ICFG_IOC);
222
223 return fence;
224}
225
226static void
227v3d_gpu_reset_for_timeout(struct v3d_dev *v3d, struct drm_sched_job *sched_job)
228{
229 enum v3d_queue q;
174 230
175 mutex_lock(&v3d->reset_lock); 231 mutex_lock(&v3d->reset_lock);
176 232
@@ -195,6 +251,39 @@ v3d_job_timedout(struct drm_sched_job *sched_job)
195 mutex_unlock(&v3d->reset_lock); 251 mutex_unlock(&v3d->reset_lock);
196} 252}
197 253
254static void
255v3d_job_timedout(struct drm_sched_job *sched_job)
256{
257 struct v3d_job *job = to_v3d_job(sched_job);
258 struct v3d_exec_info *exec = job->exec;
259 struct v3d_dev *v3d = exec->v3d;
260 enum v3d_queue job_q = job == &exec->bin ? V3D_BIN : V3D_RENDER;
261 u32 ctca = V3D_CORE_READ(0, V3D_CLE_CTNCA(job_q));
262 u32 ctra = V3D_CORE_READ(0, V3D_CLE_CTNRA(job_q));
263
264 /* If the current address or return address have changed, then
265 * the GPU has probably made progress and we should delay the
266 * reset. This could fail if the GPU got in an infinite loop
267 * in the CL, but that is pretty unlikely outside of an i-g-t
268 * testcase.
269 */
270 if (job->timedout_ctca != ctca || job->timedout_ctra != ctra) {
271 job->timedout_ctca = ctca;
272 job->timedout_ctra = ctra;
273 return;
274 }
275
276 v3d_gpu_reset_for_timeout(v3d, sched_job);
277}
278
279static void
280v3d_tfu_job_timedout(struct drm_sched_job *sched_job)
281{
282 struct v3d_tfu_job *job = to_tfu_job(sched_job);
283
284 v3d_gpu_reset_for_timeout(job->v3d, sched_job);
285}
286
198static const struct drm_sched_backend_ops v3d_sched_ops = { 287static const struct drm_sched_backend_ops v3d_sched_ops = {
199 .dependency = v3d_job_dependency, 288 .dependency = v3d_job_dependency,
200 .run_job = v3d_job_run, 289 .run_job = v3d_job_run,
@@ -202,6 +291,13 @@ static const struct drm_sched_backend_ops v3d_sched_ops = {
202 .free_job = v3d_job_free 291 .free_job = v3d_job_free
203}; 292};
204 293
294static const struct drm_sched_backend_ops v3d_tfu_sched_ops = {
295 .dependency = v3d_tfu_job_dependency,
296 .run_job = v3d_tfu_job_run,
297 .timedout_job = v3d_tfu_job_timedout,
298 .free_job = v3d_tfu_job_free
299};
300
205int 301int
206v3d_sched_init(struct v3d_dev *v3d) 302v3d_sched_init(struct v3d_dev *v3d)
207{ 303{
@@ -232,6 +328,19 @@ v3d_sched_init(struct v3d_dev *v3d)
232 return ret; 328 return ret;
233 } 329 }
234 330
331 ret = drm_sched_init(&v3d->queue[V3D_TFU].sched,
332 &v3d_tfu_sched_ops,
333 hw_jobs_limit, job_hang_limit,
334 msecs_to_jiffies(hang_limit_ms),
335 "v3d_tfu");
336 if (ret) {
337 dev_err(v3d->dev, "Failed to create TFU scheduler: %d.",
338 ret);
339 drm_sched_fini(&v3d->queue[V3D_RENDER].sched);
340 drm_sched_fini(&v3d->queue[V3D_BIN].sched);
341 return ret;
342 }
343
235 return 0; 344 return 0;
236} 345}
237 346
diff --git a/drivers/gpu/drm/v3d/v3d_trace.h b/drivers/gpu/drm/v3d/v3d_trace.h
index 85dd351e1e09..edd984afa33f 100644
--- a/drivers/gpu/drm/v3d/v3d_trace.h
+++ b/drivers/gpu/drm/v3d/v3d_trace.h
@@ -12,6 +12,28 @@
12#define TRACE_SYSTEM v3d 12#define TRACE_SYSTEM v3d
13#define TRACE_INCLUDE_FILE v3d_trace 13#define TRACE_INCLUDE_FILE v3d_trace
14 14
15TRACE_EVENT(v3d_submit_cl_ioctl,
16 TP_PROTO(struct drm_device *dev, u32 ct1qba, u32 ct1qea),
17 TP_ARGS(dev, ct1qba, ct1qea),
18
19 TP_STRUCT__entry(
20 __field(u32, dev)
21 __field(u32, ct1qba)
22 __field(u32, ct1qea)
23 ),
24
25 TP_fast_assign(
26 __entry->dev = dev->primary->index;
27 __entry->ct1qba = ct1qba;
28 __entry->ct1qea = ct1qea;
29 ),
30
31 TP_printk("dev=%u, RCL 0x%08x..0x%08x",
32 __entry->dev,
33 __entry->ct1qba,
34 __entry->ct1qea)
35);
36
15TRACE_EVENT(v3d_submit_cl, 37TRACE_EVENT(v3d_submit_cl,
16 TP_PROTO(struct drm_device *dev, bool is_render, 38 TP_PROTO(struct drm_device *dev, bool is_render,
17 uint64_t seqno, 39 uint64_t seqno,
@@ -42,6 +64,105 @@ TRACE_EVENT(v3d_submit_cl,
42 __entry->ctnqea) 64 __entry->ctnqea)
43); 65);
44 66
67TRACE_EVENT(v3d_bcl_irq,
68 TP_PROTO(struct drm_device *dev,
69 uint64_t seqno),
70 TP_ARGS(dev, seqno),
71
72 TP_STRUCT__entry(
73 __field(u32, dev)
74 __field(u64, seqno)
75 ),
76
77 TP_fast_assign(
78 __entry->dev = dev->primary->index;
79 __entry->seqno = seqno;
80 ),
81
82 TP_printk("dev=%u, seqno=%llu",
83 __entry->dev,
84 __entry->seqno)
85);
86
87TRACE_EVENT(v3d_rcl_irq,
88 TP_PROTO(struct drm_device *dev,
89 uint64_t seqno),
90 TP_ARGS(dev, seqno),
91
92 TP_STRUCT__entry(
93 __field(u32, dev)
94 __field(u64, seqno)
95 ),
96
97 TP_fast_assign(
98 __entry->dev = dev->primary->index;
99 __entry->seqno = seqno;
100 ),
101
102 TP_printk("dev=%u, seqno=%llu",
103 __entry->dev,
104 __entry->seqno)
105);
106
107TRACE_EVENT(v3d_tfu_irq,
108 TP_PROTO(struct drm_device *dev,
109 uint64_t seqno),
110 TP_ARGS(dev, seqno),
111
112 TP_STRUCT__entry(
113 __field(u32, dev)
114 __field(u64, seqno)
115 ),
116
117 TP_fast_assign(
118 __entry->dev = dev->primary->index;
119 __entry->seqno = seqno;
120 ),
121
122 TP_printk("dev=%u, seqno=%llu",
123 __entry->dev,
124 __entry->seqno)
125);
126
127TRACE_EVENT(v3d_submit_tfu_ioctl,
128 TP_PROTO(struct drm_device *dev, u32 iia),
129 TP_ARGS(dev, iia),
130
131 TP_STRUCT__entry(
132 __field(u32, dev)
133 __field(u32, iia)
134 ),
135
136 TP_fast_assign(
137 __entry->dev = dev->primary->index;
138 __entry->iia = iia;
139 ),
140
141 TP_printk("dev=%u, IIA 0x%08x",
142 __entry->dev,
143 __entry->iia)
144);
145
146TRACE_EVENT(v3d_submit_tfu,
147 TP_PROTO(struct drm_device *dev,
148 uint64_t seqno),
149 TP_ARGS(dev, seqno),
150
151 TP_STRUCT__entry(
152 __field(u32, dev)
153 __field(u64, seqno)
154 ),
155
156 TP_fast_assign(
157 __entry->dev = dev->primary->index;
158 __entry->seqno = seqno;
159 ),
160
161 TP_printk("dev=%u, seqno=%llu",
162 __entry->dev,
163 __entry->seqno)
164);
165
45TRACE_EVENT(v3d_reset_begin, 166TRACE_EVENT(v3d_reset_begin,
46 TP_PROTO(struct drm_device *dev), 167 TP_PROTO(struct drm_device *dev),
47 TP_ARGS(dev), 168 TP_ARGS(dev),
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index bd6ef1f31822..4f87b03f837d 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -338,6 +338,7 @@ struct vc4_plane_state {
338 u32 pos0_offset; 338 u32 pos0_offset;
339 u32 pos2_offset; 339 u32 pos2_offset;
340 u32 ptr0_offset; 340 u32 ptr0_offset;
341 u32 lbm_offset;
341 342
342 /* Offset where the plane's dlist was last stored in the 343 /* Offset where the plane's dlist was last stored in the
343 * hardware at vc4_crtc_atomic_flush() time. 344 * hardware at vc4_crtc_atomic_flush() time.
@@ -369,6 +370,11 @@ struct vc4_plane_state {
369 * to enable background color fill. 370 * to enable background color fill.
370 */ 371 */
371 bool needs_bg_fill; 372 bool needs_bg_fill;
373
374 /* Mark the dlist as initialized. Useful to avoid initializing it twice
375 * when async update is not possible.
376 */
377 bool dlist_initialized;
372}; 378};
373 379
374static inline struct vc4_plane_state * 380static inline struct vc4_plane_state *
diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c
index 41881ce4132d..aea2b8dfec17 100644
--- a/drivers/gpu/drm/vc4/vc4_gem.c
+++ b/drivers/gpu/drm/vc4/vc4_gem.c
@@ -681,7 +681,7 @@ vc4_queue_submit(struct drm_device *dev, struct vc4_exec_info *exec,
681 exec->fence = &fence->base; 681 exec->fence = &fence->base;
682 682
683 if (out_sync) 683 if (out_sync)
684 drm_syncobj_replace_fence(out_sync, 0, exec->fence); 684 drm_syncobj_replace_fence(out_sync, exec->fence);
685 685
686 vc4_update_bo_seqnos(exec, seqno); 686 vc4_update_bo_seqnos(exec, seqno);
687 687
diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
index c3ded0ba0441..75db62cbe468 100644
--- a/drivers/gpu/drm/vc4/vc4_plane.c
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -154,6 +154,7 @@ static struct drm_plane_state *vc4_plane_duplicate_state(struct drm_plane *plane
154 return NULL; 154 return NULL;
155 155
156 memset(&vc4_state->lbm, 0, sizeof(vc4_state->lbm)); 156 memset(&vc4_state->lbm, 0, sizeof(vc4_state->lbm));
157 vc4_state->dlist_initialized = 0;
157 158
158 __drm_atomic_helper_plane_duplicate_state(plane, &vc4_state->base); 159 __drm_atomic_helper_plane_duplicate_state(plane, &vc4_state->base);
159 160
@@ -259,14 +260,12 @@ static u32 vc4_get_scl_field(struct drm_plane_state *state, int plane)
259 260
260static int vc4_plane_setup_clipping_and_scaling(struct drm_plane_state *state) 261static int vc4_plane_setup_clipping_and_scaling(struct drm_plane_state *state)
261{ 262{
262 struct drm_plane *plane = state->plane;
263 struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); 263 struct vc4_plane_state *vc4_state = to_vc4_plane_state(state);
264 struct drm_framebuffer *fb = state->fb; 264 struct drm_framebuffer *fb = state->fb;
265 struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0); 265 struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0);
266 u32 subpixel_src_mask = (1 << 16) - 1; 266 u32 subpixel_src_mask = (1 << 16) - 1;
267 u32 format = fb->format->format; 267 u32 format = fb->format->format;
268 int num_planes = fb->format->num_planes; 268 int num_planes = fb->format->num_planes;
269 int min_scale = 1, max_scale = INT_MAX;
270 struct drm_crtc_state *crtc_state; 269 struct drm_crtc_state *crtc_state;
271 u32 h_subsample, v_subsample; 270 u32 h_subsample, v_subsample;
272 int i, ret; 271 int i, ret;
@@ -278,21 +277,8 @@ static int vc4_plane_setup_clipping_and_scaling(struct drm_plane_state *state)
278 return -EINVAL; 277 return -EINVAL;
279 } 278 }
280 279
281 /* No configuring scaling on the cursor plane, since it gets 280 ret = drm_atomic_helper_check_plane_state(state, crtc_state, 1,
282 * non-vblank-synced updates, and scaling requires LBM changes which 281 INT_MAX, true, true);
283 * have to be vblank-synced.
284 */
285 if (plane->type == DRM_PLANE_TYPE_CURSOR) {
286 min_scale = DRM_PLANE_HELPER_NO_SCALING;
287 max_scale = DRM_PLANE_HELPER_NO_SCALING;
288 } else {
289 min_scale = 1;
290 max_scale = INT_MAX;
291 }
292
293 ret = drm_atomic_helper_check_plane_state(state, crtc_state,
294 min_scale, max_scale,
295 true, true);
296 if (ret) 282 if (ret)
297 return ret; 283 return ret;
298 284
@@ -395,10 +381,13 @@ static u32 vc4_lbm_size(struct drm_plane_state *state)
395 u32 pix_per_line = max(vc4_state->src_w[0], (u32)vc4_state->crtc_w); 381 u32 pix_per_line = max(vc4_state->src_w[0], (u32)vc4_state->crtc_w);
396 u32 lbm; 382 u32 lbm;
397 383
384 /* LBM is not needed when there's no vertical scaling. */
385 if (vc4_state->y_scaling[0] == VC4_SCALING_NONE &&
386 vc4_state->y_scaling[1] == VC4_SCALING_NONE)
387 return 0;
388
398 if (!vc4_state->is_yuv) { 389 if (!vc4_state->is_yuv) {
399 if (vc4_state->is_unity) 390 if (vc4_state->y_scaling[0] == VC4_SCALING_TPZ)
400 return 0;
401 else if (vc4_state->y_scaling[0] == VC4_SCALING_TPZ)
402 lbm = pix_per_line * 8; 391 lbm = pix_per_line * 8;
403 else { 392 else {
404 /* In special cases, this multiplier might be 12. */ 393 /* In special cases, this multiplier might be 12. */
@@ -449,6 +438,43 @@ static void vc4_write_scaling_parameters(struct drm_plane_state *state,
449 } 438 }
450} 439}
451 440
441static int vc4_plane_allocate_lbm(struct drm_plane_state *state)
442{
443 struct vc4_dev *vc4 = to_vc4_dev(state->plane->dev);
444 struct vc4_plane_state *vc4_state = to_vc4_plane_state(state);
445 unsigned long irqflags;
446 u32 lbm_size;
447
448 lbm_size = vc4_lbm_size(state);
449 if (!lbm_size)
450 return 0;
451
452 if (WARN_ON(!vc4_state->lbm_offset))
453 return -EINVAL;
454
455 /* Allocate the LBM memory that the HVS will use for temporary
456 * storage due to our scaling/format conversion.
457 */
458 if (!vc4_state->lbm.allocated) {
459 int ret;
460
461 spin_lock_irqsave(&vc4->hvs->mm_lock, irqflags);
462 ret = drm_mm_insert_node_generic(&vc4->hvs->lbm_mm,
463 &vc4_state->lbm,
464 lbm_size, 32, 0, 0);
465 spin_unlock_irqrestore(&vc4->hvs->mm_lock, irqflags);
466
467 if (ret)
468 return ret;
469 } else {
470 WARN_ON_ONCE(lbm_size != vc4_state->lbm.size);
471 }
472
473 vc4_state->dlist[vc4_state->lbm_offset] = vc4_state->lbm.start;
474
475 return 0;
476}
477
452/* Writes out a full display list for an active plane to the plane's 478/* Writes out a full display list for an active plane to the plane's
453 * private dlist state. 479 * private dlist state.
454 */ 480 */
@@ -466,31 +492,14 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
466 bool mix_plane_alpha; 492 bool mix_plane_alpha;
467 bool covers_screen; 493 bool covers_screen;
468 u32 scl0, scl1, pitch0; 494 u32 scl0, scl1, pitch0;
469 u32 lbm_size, tiling; 495 u32 tiling;
470 unsigned long irqflags;
471 u32 hvs_format = format->hvs; 496 u32 hvs_format = format->hvs;
472 int ret, i; 497 int ret, i;
473 498
474 ret = vc4_plane_setup_clipping_and_scaling(state); 499 if (vc4_state->dlist_initialized)
475 if (ret) 500 return 0;
476 return ret;
477
478 /* Allocate the LBM memory that the HVS will use for temporary
479 * storage due to our scaling/format conversion.
480 */
481 lbm_size = vc4_lbm_size(state);
482 if (lbm_size) {
483 if (!vc4_state->lbm.allocated) {
484 spin_lock_irqsave(&vc4->hvs->mm_lock, irqflags);
485 ret = drm_mm_insert_node_generic(&vc4->hvs->lbm_mm,
486 &vc4_state->lbm,
487 lbm_size, 32, 0, 0);
488 spin_unlock_irqrestore(&vc4->hvs->mm_lock, irqflags);
489 } else {
490 WARN_ON_ONCE(lbm_size != vc4_state->lbm.size);
491 }
492 }
493 501
502 ret = vc4_plane_setup_clipping_and_scaling(state);
494 if (ret) 503 if (ret)
495 return ret; 504 return ret;
496 505
@@ -714,15 +723,18 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
714 vc4_dlist_write(vc4_state, SCALER_CSC2_ITR_R_601_5); 723 vc4_dlist_write(vc4_state, SCALER_CSC2_ITR_R_601_5);
715 } 724 }
716 725
726 vc4_state->lbm_offset = 0;
727
717 if (vc4_state->x_scaling[0] != VC4_SCALING_NONE || 728 if (vc4_state->x_scaling[0] != VC4_SCALING_NONE ||
718 vc4_state->x_scaling[1] != VC4_SCALING_NONE || 729 vc4_state->x_scaling[1] != VC4_SCALING_NONE ||
719 vc4_state->y_scaling[0] != VC4_SCALING_NONE || 730 vc4_state->y_scaling[0] != VC4_SCALING_NONE ||
720 vc4_state->y_scaling[1] != VC4_SCALING_NONE) { 731 vc4_state->y_scaling[1] != VC4_SCALING_NONE) {
721 /* LBM Base Address. */ 732 /* Reserve a slot for the LBM Base Address. The real value will
733 * be set when calling vc4_plane_allocate_lbm().
734 */
722 if (vc4_state->y_scaling[0] != VC4_SCALING_NONE || 735 if (vc4_state->y_scaling[0] != VC4_SCALING_NONE ||
723 vc4_state->y_scaling[1] != VC4_SCALING_NONE) { 736 vc4_state->y_scaling[1] != VC4_SCALING_NONE)
724 vc4_dlist_write(vc4_state, vc4_state->lbm.start); 737 vc4_state->lbm_offset = vc4_state->dlist_count++;
725 }
726 738
727 if (num_planes > 1) { 739 if (num_planes > 1) {
728 /* Emit Cb/Cr as channel 0 and Y as channel 740 /* Emit Cb/Cr as channel 0 and Y as channel
@@ -768,6 +780,13 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
768 vc4_state->needs_bg_fill = fb->format->has_alpha || !covers_screen || 780 vc4_state->needs_bg_fill = fb->format->has_alpha || !covers_screen ||
769 state->alpha != DRM_BLEND_ALPHA_OPAQUE; 781 state->alpha != DRM_BLEND_ALPHA_OPAQUE;
770 782
783 /* Flag the dlist as initialized to avoid checking it twice in case
784 * the async update check already called vc4_plane_mode_set() and
785 * decided to fallback to sync update because async update was not
786 * possible.
787 */
788 vc4_state->dlist_initialized = 1;
789
771 return 0; 790 return 0;
772} 791}
773 792
@@ -782,13 +801,18 @@ static int vc4_plane_atomic_check(struct drm_plane *plane,
782 struct drm_plane_state *state) 801 struct drm_plane_state *state)
783{ 802{
784 struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); 803 struct vc4_plane_state *vc4_state = to_vc4_plane_state(state);
804 int ret;
785 805
786 vc4_state->dlist_count = 0; 806 vc4_state->dlist_count = 0;
787 807
788 if (plane_enabled(state)) 808 if (!plane_enabled(state))
789 return vc4_plane_mode_set(plane, state);
790 else
791 return 0; 809 return 0;
810
811 ret = vc4_plane_mode_set(plane, state);
812 if (ret)
813 return ret;
814
815 return vc4_plane_allocate_lbm(state);
792} 816}
793 817
794static void vc4_plane_atomic_update(struct drm_plane *plane, 818static void vc4_plane_atomic_update(struct drm_plane *plane,
@@ -856,30 +880,50 @@ static void vc4_plane_atomic_async_update(struct drm_plane *plane,
856{ 880{
857 struct vc4_plane_state *vc4_state, *new_vc4_state; 881 struct vc4_plane_state *vc4_state, *new_vc4_state;
858 882
859 if (plane->state->fb != state->fb) { 883 drm_atomic_set_fb_for_plane(plane->state, state->fb);
860 vc4_plane_async_set_fb(plane, state->fb);
861 drm_atomic_set_fb_for_plane(plane->state, state->fb);
862 }
863
864 /* Set the cursor's position on the screen. This is the
865 * expected change from the drm_mode_cursor_universal()
866 * helper.
867 */
868 plane->state->crtc_x = state->crtc_x; 884 plane->state->crtc_x = state->crtc_x;
869 plane->state->crtc_y = state->crtc_y; 885 plane->state->crtc_y = state->crtc_y;
870 886 plane->state->crtc_w = state->crtc_w;
871 /* Allow changing the start position within the cursor BO, if 887 plane->state->crtc_h = state->crtc_h;
872 * that matters.
873 */
874 plane->state->src_x = state->src_x; 888 plane->state->src_x = state->src_x;
875 plane->state->src_y = state->src_y; 889 plane->state->src_y = state->src_y;
876 890 plane->state->src_w = state->src_w;
877 /* Update the display list based on the new crtc_x/y. */ 891 plane->state->src_h = state->src_h;
878 vc4_plane_atomic_check(plane, state); 892 plane->state->src_h = state->src_h;
893 plane->state->alpha = state->alpha;
894 plane->state->pixel_blend_mode = state->pixel_blend_mode;
895 plane->state->rotation = state->rotation;
896 plane->state->zpos = state->zpos;
897 plane->state->normalized_zpos = state->normalized_zpos;
898 plane->state->color_encoding = state->color_encoding;
899 plane->state->color_range = state->color_range;
900 plane->state->src = state->src;
901 plane->state->dst = state->dst;
902 plane->state->visible = state->visible;
879 903
880 new_vc4_state = to_vc4_plane_state(state); 904 new_vc4_state = to_vc4_plane_state(state);
881 vc4_state = to_vc4_plane_state(plane->state); 905 vc4_state = to_vc4_plane_state(plane->state);
882 906
907 vc4_state->crtc_x = new_vc4_state->crtc_x;
908 vc4_state->crtc_y = new_vc4_state->crtc_y;
909 vc4_state->crtc_h = new_vc4_state->crtc_h;
910 vc4_state->crtc_w = new_vc4_state->crtc_w;
911 vc4_state->src_x = new_vc4_state->src_x;
912 vc4_state->src_y = new_vc4_state->src_y;
913 memcpy(vc4_state->src_w, new_vc4_state->src_w,
914 sizeof(vc4_state->src_w));
915 memcpy(vc4_state->src_h, new_vc4_state->src_h,
916 sizeof(vc4_state->src_h));
917 memcpy(vc4_state->x_scaling, new_vc4_state->x_scaling,
918 sizeof(vc4_state->x_scaling));
919 memcpy(vc4_state->y_scaling, new_vc4_state->y_scaling,
920 sizeof(vc4_state->y_scaling));
921 vc4_state->is_unity = new_vc4_state->is_unity;
922 vc4_state->is_yuv = new_vc4_state->is_yuv;
923 memcpy(vc4_state->offsets, new_vc4_state->offsets,
924 sizeof(vc4_state->offsets));
925 vc4_state->needs_bg_fill = new_vc4_state->needs_bg_fill;
926
883 /* Update the current vc4_state pos0, pos2 and ptr0 dlist entries. */ 927 /* Update the current vc4_state pos0, pos2 and ptr0 dlist entries. */
884 vc4_state->dlist[vc4_state->pos0_offset] = 928 vc4_state->dlist[vc4_state->pos0_offset] =
885 new_vc4_state->dlist[vc4_state->pos0_offset]; 929 new_vc4_state->dlist[vc4_state->pos0_offset];
@@ -903,13 +947,38 @@ static void vc4_plane_atomic_async_update(struct drm_plane *plane,
903static int vc4_plane_atomic_async_check(struct drm_plane *plane, 947static int vc4_plane_atomic_async_check(struct drm_plane *plane,
904 struct drm_plane_state *state) 948 struct drm_plane_state *state)
905{ 949{
906 /* No configuring new scaling in the fast path. */ 950 struct vc4_plane_state *old_vc4_state, *new_vc4_state;
907 if (plane->state->crtc_w != state->crtc_w || 951 int ret;
908 plane->state->crtc_h != state->crtc_h || 952 u32 i;
909 plane->state->src_w != state->src_w || 953
910 plane->state->src_h != state->src_h) 954 ret = vc4_plane_mode_set(plane, state);
955 if (ret)
956 return ret;
957
958 old_vc4_state = to_vc4_plane_state(plane->state);
959 new_vc4_state = to_vc4_plane_state(state);
960 if (old_vc4_state->dlist_count != new_vc4_state->dlist_count ||
961 old_vc4_state->pos0_offset != new_vc4_state->pos0_offset ||
962 old_vc4_state->pos2_offset != new_vc4_state->pos2_offset ||
963 old_vc4_state->ptr0_offset != new_vc4_state->ptr0_offset ||
964 vc4_lbm_size(plane->state) != vc4_lbm_size(state))
911 return -EINVAL; 965 return -EINVAL;
912 966
967 /* Only pos0, pos2 and ptr0 DWORDS can be updated in an async update
968 * if anything else has changed, fallback to a sync update.
969 */
970 for (i = 0; i < new_vc4_state->dlist_count; i++) {
971 if (i == new_vc4_state->pos0_offset ||
972 i == new_vc4_state->pos2_offset ||
973 i == new_vc4_state->ptr0_offset ||
974 (new_vc4_state->lbm_offset &&
975 i == new_vc4_state->lbm_offset))
976 continue;
977
978 if (new_vc4_state->dlist[i] != old_vc4_state->dlist[i])
979 return -EINVAL;
980 }
981
913 return 0; 982 return 0;
914} 983}
915 984
@@ -1026,7 +1095,6 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev,
1026 struct drm_plane *plane = NULL; 1095 struct drm_plane *plane = NULL;
1027 struct vc4_plane *vc4_plane; 1096 struct vc4_plane *vc4_plane;
1028 u32 formats[ARRAY_SIZE(hvs_formats)]; 1097 u32 formats[ARRAY_SIZE(hvs_formats)];
1029 u32 num_formats = 0;
1030 int ret = 0; 1098 int ret = 0;
1031 unsigned i; 1099 unsigned i;
1032 static const uint64_t modifiers[] = { 1100 static const uint64_t modifiers[] = {
@@ -1043,20 +1111,13 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev,
1043 if (!vc4_plane) 1111 if (!vc4_plane)
1044 return ERR_PTR(-ENOMEM); 1112 return ERR_PTR(-ENOMEM);
1045 1113
1046 for (i = 0; i < ARRAY_SIZE(hvs_formats); i++) { 1114 for (i = 0; i < ARRAY_SIZE(hvs_formats); i++)
1047 /* Don't allow YUV in cursor planes, since that means 1115 formats[i] = hvs_formats[i].drm;
1048 * tuning on the scaler, which we don't allow for the 1116
1049 * cursor.
1050 */
1051 if (type != DRM_PLANE_TYPE_CURSOR ||
1052 hvs_formats[i].hvs < HVS_PIXEL_FORMAT_YCBCR_YUV420_3PLANE) {
1053 formats[num_formats++] = hvs_formats[i].drm;
1054 }
1055 }
1056 plane = &vc4_plane->base; 1117 plane = &vc4_plane->base;
1057 ret = drm_universal_plane_init(dev, plane, 0, 1118 ret = drm_universal_plane_init(dev, plane, 0,
1058 &vc4_plane_funcs, 1119 &vc4_plane_funcs,
1059 formats, num_formats, 1120 formats, ARRAY_SIZE(formats),
1060 modifiers, type, NULL); 1121 modifiers, type, NULL);
1061 1122
1062 drm_plane_helper_add(plane, &vc4_plane_helper_funcs); 1123 drm_plane_helper_add(plane, &vc4_plane_helper_funcs);
diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h
index f7e877857c1f..1deb41d42ea4 100644
--- a/drivers/gpu/drm/virtio/virtgpu_drv.h
+++ b/drivers/gpu/drm/virtio/virtgpu_drv.h
@@ -270,7 +270,7 @@ void virtio_gpu_cmd_transfer_to_host_2d(struct virtio_gpu_device *vgdev,
270 uint64_t offset, 270 uint64_t offset,
271 __le32 width, __le32 height, 271 __le32 width, __le32 height,
272 __le32 x, __le32 y, 272 __le32 x, __le32 y,
273 struct virtio_gpu_fence **fence); 273 struct virtio_gpu_fence *fence);
274void virtio_gpu_cmd_resource_flush(struct virtio_gpu_device *vgdev, 274void virtio_gpu_cmd_resource_flush(struct virtio_gpu_device *vgdev,
275 uint32_t resource_id, 275 uint32_t resource_id,
276 uint32_t x, uint32_t y, 276 uint32_t x, uint32_t y,
@@ -281,7 +281,7 @@ void virtio_gpu_cmd_set_scanout(struct virtio_gpu_device *vgdev,
281 uint32_t x, uint32_t y); 281 uint32_t x, uint32_t y);
282int virtio_gpu_object_attach(struct virtio_gpu_device *vgdev, 282int virtio_gpu_object_attach(struct virtio_gpu_device *vgdev,
283 struct virtio_gpu_object *obj, 283 struct virtio_gpu_object *obj,
284 struct virtio_gpu_fence **fence); 284 struct virtio_gpu_fence *fence);
285void virtio_gpu_object_detach(struct virtio_gpu_device *vgdev, 285void virtio_gpu_object_detach(struct virtio_gpu_device *vgdev,
286 struct virtio_gpu_object *obj); 286 struct virtio_gpu_object *obj);
287int virtio_gpu_attach_status_page(struct virtio_gpu_device *vgdev); 287int virtio_gpu_attach_status_page(struct virtio_gpu_device *vgdev);
@@ -306,23 +306,22 @@ void virtio_gpu_cmd_context_detach_resource(struct virtio_gpu_device *vgdev,
306 uint32_t resource_id); 306 uint32_t resource_id);
307void virtio_gpu_cmd_submit(struct virtio_gpu_device *vgdev, 307void virtio_gpu_cmd_submit(struct virtio_gpu_device *vgdev,
308 void *data, uint32_t data_size, 308 void *data, uint32_t data_size,
309 uint32_t ctx_id, struct virtio_gpu_fence **fence); 309 uint32_t ctx_id, struct virtio_gpu_fence *fence);
310void virtio_gpu_cmd_transfer_from_host_3d(struct virtio_gpu_device *vgdev, 310void virtio_gpu_cmd_transfer_from_host_3d(struct virtio_gpu_device *vgdev,
311 uint32_t resource_id, uint32_t ctx_id, 311 uint32_t resource_id, uint32_t ctx_id,
312 uint64_t offset, uint32_t level, 312 uint64_t offset, uint32_t level,
313 struct virtio_gpu_box *box, 313 struct virtio_gpu_box *box,
314 struct virtio_gpu_fence **fence); 314 struct virtio_gpu_fence *fence);
315void virtio_gpu_cmd_transfer_to_host_3d(struct virtio_gpu_device *vgdev, 315void virtio_gpu_cmd_transfer_to_host_3d(struct virtio_gpu_device *vgdev,
316 struct virtio_gpu_object *bo, 316 struct virtio_gpu_object *bo,
317 uint32_t ctx_id, 317 uint32_t ctx_id,
318 uint64_t offset, uint32_t level, 318 uint64_t offset, uint32_t level,
319 struct virtio_gpu_box *box, 319 struct virtio_gpu_box *box,
320 struct virtio_gpu_fence **fence); 320 struct virtio_gpu_fence *fence);
321void 321void
322virtio_gpu_cmd_resource_create_3d(struct virtio_gpu_device *vgdev, 322virtio_gpu_cmd_resource_create_3d(struct virtio_gpu_device *vgdev,
323 struct virtio_gpu_object *bo, 323 struct virtio_gpu_object *bo,
324 struct virtio_gpu_resource_create_3d *rc_3d, 324 struct virtio_gpu_resource_create_3d *rc_3d);
325 struct virtio_gpu_fence **fence);
326void virtio_gpu_ctrl_ack(struct virtqueue *vq); 325void virtio_gpu_ctrl_ack(struct virtqueue *vq);
327void virtio_gpu_cursor_ack(struct virtqueue *vq); 326void virtio_gpu_cursor_ack(struct virtqueue *vq);
328void virtio_gpu_fence_ack(struct virtqueue *vq); 327void virtio_gpu_fence_ack(struct virtqueue *vq);
@@ -355,7 +354,7 @@ struct virtio_gpu_fence *virtio_gpu_fence_alloc(
355void virtio_gpu_fence_cleanup(struct virtio_gpu_fence *fence); 354void virtio_gpu_fence_cleanup(struct virtio_gpu_fence *fence);
356int virtio_gpu_fence_emit(struct virtio_gpu_device *vgdev, 355int virtio_gpu_fence_emit(struct virtio_gpu_device *vgdev,
357 struct virtio_gpu_ctrl_hdr *cmd_hdr, 356 struct virtio_gpu_ctrl_hdr *cmd_hdr,
358 struct virtio_gpu_fence **fence); 357 struct virtio_gpu_fence *fence);
359void virtio_gpu_fence_event_process(struct virtio_gpu_device *vdev, 358void virtio_gpu_fence_event_process(struct virtio_gpu_device *vdev,
360 u64 last_seq); 359 u64 last_seq);
361 360
diff --git a/drivers/gpu/drm/virtio/virtgpu_fence.c b/drivers/gpu/drm/virtio/virtgpu_fence.c
index 6b5d92215cfb..4d6826b27814 100644
--- a/drivers/gpu/drm/virtio/virtgpu_fence.c
+++ b/drivers/gpu/drm/virtio/virtgpu_fence.c
@@ -91,19 +91,19 @@ void virtio_gpu_fence_cleanup(struct virtio_gpu_fence *fence)
91 91
92int virtio_gpu_fence_emit(struct virtio_gpu_device *vgdev, 92int virtio_gpu_fence_emit(struct virtio_gpu_device *vgdev,
93 struct virtio_gpu_ctrl_hdr *cmd_hdr, 93 struct virtio_gpu_ctrl_hdr *cmd_hdr,
94 struct virtio_gpu_fence **fence) 94 struct virtio_gpu_fence *fence)
95{ 95{
96 struct virtio_gpu_fence_driver *drv = &vgdev->fence_drv; 96 struct virtio_gpu_fence_driver *drv = &vgdev->fence_drv;
97 unsigned long irq_flags; 97 unsigned long irq_flags;
98 98
99 spin_lock_irqsave(&drv->lock, irq_flags); 99 spin_lock_irqsave(&drv->lock, irq_flags);
100 (*fence)->seq = ++drv->sync_seq; 100 fence->seq = ++drv->sync_seq;
101 dma_fence_get(&(*fence)->f); 101 dma_fence_get(&fence->f);
102 list_add_tail(&(*fence)->node, &drv->fences); 102 list_add_tail(&fence->node, &drv->fences);
103 spin_unlock_irqrestore(&drv->lock, irq_flags); 103 spin_unlock_irqrestore(&drv->lock, irq_flags);
104 104
105 cmd_hdr->flags |= cpu_to_le32(VIRTIO_GPU_FLAG_FENCE); 105 cmd_hdr->flags |= cpu_to_le32(VIRTIO_GPU_FLAG_FENCE);
106 cmd_hdr->fence_id = cpu_to_le64((*fence)->seq); 106 cmd_hdr->fence_id = cpu_to_le64(fence->seq);
107 return 0; 107 return 0;
108} 108}
109 109
diff --git a/drivers/gpu/drm/virtio/virtgpu_ioctl.c b/drivers/gpu/drm/virtio/virtgpu_ioctl.c
index 340f2513d829..161b80fee492 100644
--- a/drivers/gpu/drm/virtio/virtgpu_ioctl.c
+++ b/drivers/gpu/drm/virtio/virtgpu_ioctl.c
@@ -221,7 +221,7 @@ static int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data,
221 } 221 }
222 222
223 virtio_gpu_cmd_submit(vgdev, buf, exbuf->size, 223 virtio_gpu_cmd_submit(vgdev, buf, exbuf->size,
224 vfpriv->ctx_id, &out_fence); 224 vfpriv->ctx_id, out_fence);
225 225
226 ttm_eu_fence_buffer_objects(&ticket, &validate_list, &out_fence->f); 226 ttm_eu_fence_buffer_objects(&ticket, &validate_list, &out_fence->f);
227 227
@@ -348,8 +348,8 @@ static int virtio_gpu_resource_create_ioctl(struct drm_device *dev, void *data,
348 goto fail_backoff; 348 goto fail_backoff;
349 } 349 }
350 350
351 virtio_gpu_cmd_resource_create_3d(vgdev, qobj, &rc_3d, NULL); 351 virtio_gpu_cmd_resource_create_3d(vgdev, qobj, &rc_3d);
352 ret = virtio_gpu_object_attach(vgdev, qobj, &fence); 352 ret = virtio_gpu_object_attach(vgdev, qobj, fence);
353 if (ret) { 353 if (ret) {
354 virtio_gpu_fence_cleanup(fence); 354 virtio_gpu_fence_cleanup(fence);
355 goto fail_backoff; 355 goto fail_backoff;
@@ -450,7 +450,7 @@ static int virtio_gpu_transfer_from_host_ioctl(struct drm_device *dev,
450 virtio_gpu_cmd_transfer_from_host_3d 450 virtio_gpu_cmd_transfer_from_host_3d
451 (vgdev, qobj->hw_res_handle, 451 (vgdev, qobj->hw_res_handle,
452 vfpriv->ctx_id, offset, args->level, 452 vfpriv->ctx_id, offset, args->level,
453 &box, &fence); 453 &box, fence);
454 reservation_object_add_excl_fence(qobj->tbo.resv, 454 reservation_object_add_excl_fence(qobj->tbo.resv,
455 &fence->f); 455 &fence->f);
456 456
@@ -504,7 +504,7 @@ static int virtio_gpu_transfer_to_host_ioctl(struct drm_device *dev, void *data,
504 virtio_gpu_cmd_transfer_to_host_3d 504 virtio_gpu_cmd_transfer_to_host_3d
505 (vgdev, qobj, 505 (vgdev, qobj,
506 vfpriv ? vfpriv->ctx_id : 0, offset, 506 vfpriv ? vfpriv->ctx_id : 0, offset,
507 args->level, &box, &fence); 507 args->level, &box, fence);
508 reservation_object_add_excl_fence(qobj->tbo.resv, 508 reservation_object_add_excl_fence(qobj->tbo.resv,
509 &fence->f); 509 &fence->f);
510 dma_fence_put(&fence->f); 510 dma_fence_put(&fence->f);
diff --git a/drivers/gpu/drm/virtio/virtgpu_plane.c b/drivers/gpu/drm/virtio/virtgpu_plane.c
index b84ac8c25856..ead5c53d4e21 100644
--- a/drivers/gpu/drm/virtio/virtgpu_plane.c
+++ b/drivers/gpu/drm/virtio/virtgpu_plane.c
@@ -204,7 +204,7 @@ static void virtio_gpu_cursor_plane_update(struct drm_plane *plane,
204 (vgdev, bo, 0, 204 (vgdev, bo, 0,
205 cpu_to_le32(plane->state->crtc_w), 205 cpu_to_le32(plane->state->crtc_w),
206 cpu_to_le32(plane->state->crtc_h), 206 cpu_to_le32(plane->state->crtc_h),
207 0, 0, &vgfb->fence); 207 0, 0, vgfb->fence);
208 ret = virtio_gpu_object_reserve(bo, false); 208 ret = virtio_gpu_object_reserve(bo, false);
209 if (!ret) { 209 if (!ret) {
210 reservation_object_add_excl_fence(bo->tbo.resv, 210 reservation_object_add_excl_fence(bo->tbo.resv,
diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c
index 2c6764f08f18..e27c4aedb809 100644
--- a/drivers/gpu/drm/virtio/virtgpu_vq.c
+++ b/drivers/gpu/drm/virtio/virtgpu_vq.c
@@ -298,7 +298,7 @@ static int virtio_gpu_queue_ctrl_buffer(struct virtio_gpu_device *vgdev,
298static int virtio_gpu_queue_fenced_ctrl_buffer(struct virtio_gpu_device *vgdev, 298static int virtio_gpu_queue_fenced_ctrl_buffer(struct virtio_gpu_device *vgdev,
299 struct virtio_gpu_vbuffer *vbuf, 299 struct virtio_gpu_vbuffer *vbuf,
300 struct virtio_gpu_ctrl_hdr *hdr, 300 struct virtio_gpu_ctrl_hdr *hdr,
301 struct virtio_gpu_fence **fence) 301 struct virtio_gpu_fence *fence)
302{ 302{
303 struct virtqueue *vq = vgdev->ctrlq.vq; 303 struct virtqueue *vq = vgdev->ctrlq.vq;
304 int rc; 304 int rc;
@@ -405,7 +405,7 @@ void virtio_gpu_cmd_unref_resource(struct virtio_gpu_device *vgdev,
405 405
406static void virtio_gpu_cmd_resource_inval_backing(struct virtio_gpu_device *vgdev, 406static void virtio_gpu_cmd_resource_inval_backing(struct virtio_gpu_device *vgdev,
407 uint32_t resource_id, 407 uint32_t resource_id,
408 struct virtio_gpu_fence **fence) 408 struct virtio_gpu_fence *fence)
409{ 409{
410 struct virtio_gpu_resource_detach_backing *cmd_p; 410 struct virtio_gpu_resource_detach_backing *cmd_p;
411 struct virtio_gpu_vbuffer *vbuf; 411 struct virtio_gpu_vbuffer *vbuf;
@@ -467,7 +467,7 @@ void virtio_gpu_cmd_transfer_to_host_2d(struct virtio_gpu_device *vgdev,
467 uint64_t offset, 467 uint64_t offset,
468 __le32 width, __le32 height, 468 __le32 width, __le32 height,
469 __le32 x, __le32 y, 469 __le32 x, __le32 y,
470 struct virtio_gpu_fence **fence) 470 struct virtio_gpu_fence *fence)
471{ 471{
472 struct virtio_gpu_transfer_to_host_2d *cmd_p; 472 struct virtio_gpu_transfer_to_host_2d *cmd_p;
473 struct virtio_gpu_vbuffer *vbuf; 473 struct virtio_gpu_vbuffer *vbuf;
@@ -497,7 +497,7 @@ virtio_gpu_cmd_resource_attach_backing(struct virtio_gpu_device *vgdev,
497 uint32_t resource_id, 497 uint32_t resource_id,
498 struct virtio_gpu_mem_entry *ents, 498 struct virtio_gpu_mem_entry *ents,
499 uint32_t nents, 499 uint32_t nents,
500 struct virtio_gpu_fence **fence) 500 struct virtio_gpu_fence *fence)
501{ 501{
502 struct virtio_gpu_resource_attach_backing *cmd_p; 502 struct virtio_gpu_resource_attach_backing *cmd_p;
503 struct virtio_gpu_vbuffer *vbuf; 503 struct virtio_gpu_vbuffer *vbuf;
@@ -820,8 +820,7 @@ void virtio_gpu_cmd_context_detach_resource(struct virtio_gpu_device *vgdev,
820void 820void
821virtio_gpu_cmd_resource_create_3d(struct virtio_gpu_device *vgdev, 821virtio_gpu_cmd_resource_create_3d(struct virtio_gpu_device *vgdev,
822 struct virtio_gpu_object *bo, 822 struct virtio_gpu_object *bo,
823 struct virtio_gpu_resource_create_3d *rc_3d, 823 struct virtio_gpu_resource_create_3d *rc_3d)
824 struct virtio_gpu_fence **fence)
825{ 824{
826 struct virtio_gpu_resource_create_3d *cmd_p; 825 struct virtio_gpu_resource_create_3d *cmd_p;
827 struct virtio_gpu_vbuffer *vbuf; 826 struct virtio_gpu_vbuffer *vbuf;
@@ -833,7 +832,7 @@ virtio_gpu_cmd_resource_create_3d(struct virtio_gpu_device *vgdev,
833 cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_RESOURCE_CREATE_3D); 832 cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_RESOURCE_CREATE_3D);
834 cmd_p->hdr.flags = 0; 833 cmd_p->hdr.flags = 0;
835 834
836 virtio_gpu_queue_fenced_ctrl_buffer(vgdev, vbuf, &cmd_p->hdr, fence); 835 virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
837 bo->created = true; 836 bo->created = true;
838} 837}
839 838
@@ -842,7 +841,7 @@ void virtio_gpu_cmd_transfer_to_host_3d(struct virtio_gpu_device *vgdev,
842 uint32_t ctx_id, 841 uint32_t ctx_id,
843 uint64_t offset, uint32_t level, 842 uint64_t offset, uint32_t level,
844 struct virtio_gpu_box *box, 843 struct virtio_gpu_box *box,
845 struct virtio_gpu_fence **fence) 844 struct virtio_gpu_fence *fence)
846{ 845{
847 struct virtio_gpu_transfer_host_3d *cmd_p; 846 struct virtio_gpu_transfer_host_3d *cmd_p;
848 struct virtio_gpu_vbuffer *vbuf; 847 struct virtio_gpu_vbuffer *vbuf;
@@ -870,7 +869,7 @@ void virtio_gpu_cmd_transfer_from_host_3d(struct virtio_gpu_device *vgdev,
870 uint32_t resource_id, uint32_t ctx_id, 869 uint32_t resource_id, uint32_t ctx_id,
871 uint64_t offset, uint32_t level, 870 uint64_t offset, uint32_t level,
872 struct virtio_gpu_box *box, 871 struct virtio_gpu_box *box,
873 struct virtio_gpu_fence **fence) 872 struct virtio_gpu_fence *fence)
874{ 873{
875 struct virtio_gpu_transfer_host_3d *cmd_p; 874 struct virtio_gpu_transfer_host_3d *cmd_p;
876 struct virtio_gpu_vbuffer *vbuf; 875 struct virtio_gpu_vbuffer *vbuf;
@@ -890,7 +889,7 @@ void virtio_gpu_cmd_transfer_from_host_3d(struct virtio_gpu_device *vgdev,
890 889
891void virtio_gpu_cmd_submit(struct virtio_gpu_device *vgdev, 890void virtio_gpu_cmd_submit(struct virtio_gpu_device *vgdev,
892 void *data, uint32_t data_size, 891 void *data, uint32_t data_size,
893 uint32_t ctx_id, struct virtio_gpu_fence **fence) 892 uint32_t ctx_id, struct virtio_gpu_fence *fence)
894{ 893{
895 struct virtio_gpu_cmd_submit *cmd_p; 894 struct virtio_gpu_cmd_submit *cmd_p;
896 struct virtio_gpu_vbuffer *vbuf; 895 struct virtio_gpu_vbuffer *vbuf;
@@ -910,7 +909,7 @@ void virtio_gpu_cmd_submit(struct virtio_gpu_device *vgdev,
910 909
911int virtio_gpu_object_attach(struct virtio_gpu_device *vgdev, 910int virtio_gpu_object_attach(struct virtio_gpu_device *vgdev,
912 struct virtio_gpu_object *obj, 911 struct virtio_gpu_object *obj,
913 struct virtio_gpu_fence **fence) 912 struct virtio_gpu_fence *fence)
914{ 913{
915 bool use_dma_api = !virtio_has_iommu_quirk(vgdev->vdev); 914 bool use_dma_api = !virtio_has_iommu_quirk(vgdev->vdev);
916 struct virtio_gpu_mem_entry *ents; 915 struct virtio_gpu_mem_entry *ents;
@@ -967,7 +966,7 @@ void virtio_gpu_object_detach(struct virtio_gpu_device *vgdev,
967 if (use_dma_api && obj->mapped) { 966 if (use_dma_api && obj->mapped) {
968 struct virtio_gpu_fence *fence = virtio_gpu_fence_alloc(vgdev); 967 struct virtio_gpu_fence *fence = virtio_gpu_fence_alloc(vgdev);
969 /* detach backing and wait for the host process it ... */ 968 /* detach backing and wait for the host process it ... */
970 virtio_gpu_cmd_resource_inval_backing(vgdev, obj->hw_res_handle, &fence); 969 virtio_gpu_cmd_resource_inval_backing(vgdev, obj->hw_res_handle, fence);
971 dma_fence_wait(&fence->f, true); 970 dma_fence_wait(&fence->f, true);
972 dma_fence_put(&fence->f); 971 dma_fence_put(&fence->f);
973 972
diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c
index 7041007396ae..418817600ad1 100644
--- a/drivers/gpu/drm/vkms/vkms_plane.c
+++ b/drivers/gpu/drm/vkms/vkms_plane.c
@@ -23,8 +23,11 @@ vkms_plane_duplicate_state(struct drm_plane *plane)
23 return NULL; 23 return NULL;
24 24
25 crc_data = kzalloc(sizeof(*crc_data), GFP_KERNEL); 25 crc_data = kzalloc(sizeof(*crc_data), GFP_KERNEL);
26 if (WARN_ON(!crc_data)) 26 if (!crc_data) {
27 DRM_INFO("Couldn't allocate crc_data"); 27 DRM_DEBUG_KMS("Couldn't allocate crc_data\n");
28 kfree(vkms_state);
29 return NULL;
30 }
28 31
29 vkms_state->crc_data = crc_data; 32 vkms_state->crc_data = crc_data;
30 33
@@ -138,14 +141,12 @@ static int vkms_prepare_fb(struct drm_plane *plane,
138 struct drm_plane_state *state) 141 struct drm_plane_state *state)
139{ 142{
140 struct drm_gem_object *gem_obj; 143 struct drm_gem_object *gem_obj;
141 struct vkms_gem_object *vkms_obj;
142 int ret; 144 int ret;
143 145
144 if (!state->fb) 146 if (!state->fb)
145 return 0; 147 return 0;
146 148
147 gem_obj = drm_gem_fb_get_obj(state->fb, 0); 149 gem_obj = drm_gem_fb_get_obj(state->fb, 0);
148 vkms_obj = drm_gem_to_vkms_gem(gem_obj);
149 ret = vkms_gem_vmap(gem_obj); 150 ret = vkms_gem_vmap(gem_obj);
150 if (ret) 151 if (ret)
151 DRM_ERROR("vmap failed: %d\n", ret); 152 DRM_ERROR("vmap failed: %d\n", ret);