From 2312f984285495117d559c1e928dee465a32bc49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Wed, 5 Dec 2018 20:43:02 +0100 Subject: [PATCH 01/49] drm/v3d: fix broken build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I missed one case during the recent revert of the replace_fence interface change. Fixes: 0b258ed1a219 drm: revert "expand replace_fence to support timeline point v2" Signed-off-by: Christian König Acked-by: Alex Deucher Link: https://patchwork.freedesktop.org/patch/266134/ --- drivers/gpu/drm/v3d/v3d_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/v3d/v3d_gem.c b/drivers/gpu/drm/v3d/v3d_gem.c index cb99e53f7607..05ca6319065e 100644 --- a/drivers/gpu/drm/v3d/v3d_gem.c +++ b/drivers/gpu/drm/v3d/v3d_gem.c @@ -716,7 +716,7 @@ v3d_submit_tfu_ioctl(struct drm_device *dev, void *data, /* Update the return sync object */ sync_out = drm_syncobj_find(file_priv, args->out_sync); if (sync_out) { - drm_syncobj_replace_fence(sync_out, 0, sched_done_fence); + drm_syncobj_replace_fence(sync_out, sched_done_fence); drm_syncobj_put(sync_out); } dma_fence_put(sched_done_fence); From fcc4a00294a585dfee7588410d5cc9768abc7f00 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 21 Nov 2018 10:01:29 +0100 Subject: [PATCH 02/49] drm/qxl: add spice-devel list to MAINTAINERS So qxl kernel patches are sent to the spice-devel list for review. Signed-off-by: Gerd Hoffmann Acked-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20181121090129.23506-1-kraxel@redhat.com --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 254b7b267731..135052797c86 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4735,6 +4735,7 @@ DRM DRIVER FOR QXL VIRTUAL GPU M: Dave Airlie M: Gerd Hoffmann L: virtualization@lists.linux-foundation.org +L: spice-devel@lists.freedesktop.org T: git git://anongit.freedesktop.org/drm/drm-misc S: Maintained F: drivers/gpu/drm/qxl/ From b312d8ca3a7cebe19941d969a51f2b7f899b81e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Wed, 14 Nov 2018 16:11:06 +0100 Subject: [PATCH 03/49] dma-buf: make fence sequence numbers 64 bit v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For a lot of use cases we need 64bit sequence numbers. Currently drivers overload the dma_fence structure to store the additional bits. Stop doing that and make the sequence number in the dma_fence always 64bit. For compatibility with hardware which can do only 32bit sequences the comparisons in __dma_fence_is_later only takes the lower 32bits as significant when the upper 32bits are all zero. v2: change the logic in __dma_fence_is_later Signed-off-by: Christian König Reviewed-by: Chunming Zhou Link: https://patchwork.freedesktop.org/patch/266927/ --- drivers/dma-buf/dma-fence.c | 2 +- drivers/dma-buf/sw_sync.c | 2 +- drivers/dma-buf/sync_file.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c | 2 +- drivers/gpu/drm/i915/i915_sw_fence.c | 2 +- drivers/gpu/drm/i915/intel_engine_cs.c | 2 +- drivers/gpu/drm/vgem/vgem_fence.c | 4 ++-- include/linux/dma-fence.h | 22 +++++++++++++++------- 8 files changed, 24 insertions(+), 16 deletions(-) diff --git a/drivers/dma-buf/dma-fence.c b/drivers/dma-buf/dma-fence.c index 136ec04d683f..3aa8733f832a 100644 --- a/drivers/dma-buf/dma-fence.c +++ b/drivers/dma-buf/dma-fence.c @@ -649,7 +649,7 @@ EXPORT_SYMBOL(dma_fence_wait_any_timeout); */ void dma_fence_init(struct dma_fence *fence, const struct dma_fence_ops *ops, - spinlock_t *lock, u64 context, unsigned seqno) + spinlock_t *lock, u64 context, u64 seqno) { BUG_ON(!lock); BUG_ON(!ops || !ops->get_driver_name || !ops->get_timeline_name); diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c index 53c1d6d36a64..32dcf7b4c935 100644 --- a/drivers/dma-buf/sw_sync.c +++ b/drivers/dma-buf/sw_sync.c @@ -172,7 +172,7 @@ static bool timeline_fence_enable_signaling(struct dma_fence *fence) static void timeline_fence_value_str(struct dma_fence *fence, char *str, int size) { - snprintf(str, size, "%d", fence->seqno); + snprintf(str, size, "%lld", fence->seqno); } static void timeline_fence_timeline_value_str(struct dma_fence *fence, diff --git a/drivers/dma-buf/sync_file.c b/drivers/dma-buf/sync_file.c index 35dd06479867..4f6305ca52c8 100644 --- a/drivers/dma-buf/sync_file.c +++ b/drivers/dma-buf/sync_file.c @@ -144,7 +144,7 @@ char *sync_file_get_name(struct sync_file *sync_file, char *buf, int len) } else { struct dma_fence *fence = sync_file->fence; - snprintf(buf, len, "%s-%s%llu-%d", + snprintf(buf, len, "%s-%s%llu-%lld", fence->ops->get_driver_name(fence), fence->ops->get_timeline_name(fence), fence->context, @@ -258,7 +258,7 @@ static struct sync_file *sync_file_merge(const char *name, struct sync_file *a, i_b++; } else { - if (pt_a->seqno - pt_b->seqno <= INT_MAX) + if (__dma_fence_is_later(pt_a->seqno, pt_b->seqno)) add_fence(fences, &i, pt_a); else add_fence(fences, &i, pt_b); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c index 12f2bf97611f..bfaf5c6323be 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c @@ -388,7 +388,7 @@ void amdgpu_sa_bo_dump_debug_info(struct amdgpu_sa_manager *sa_manager, soffset, eoffset, eoffset - soffset); if (i->fence) - seq_printf(m, " protected by 0x%08x on context %llu", + seq_printf(m, " protected by 0x%016llx on context %llu", i->fence->seqno, i->fence->context); seq_printf(m, "\n"); diff --git a/drivers/gpu/drm/i915/i915_sw_fence.c b/drivers/gpu/drm/i915/i915_sw_fence.c index 6dbeed079ae5..11bcdabd5177 100644 --- a/drivers/gpu/drm/i915/i915_sw_fence.c +++ b/drivers/gpu/drm/i915/i915_sw_fence.c @@ -393,7 +393,7 @@ static void timer_i915_sw_fence_wake(struct timer_list *t) if (!fence) return; - pr_notice("Asynchronous wait on fence %s:%s:%x timed out (hint:%pS)\n", + pr_notice("Asynchronous wait on fence %s:%s:%llx timed out (hint:%pS)\n", cb->dma->ops->get_driver_name(cb->dma), cb->dma->ops->get_timeline_name(cb->dma), cb->dma->seqno, diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 759c0fd58f8c..dfafa79171df 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -1239,7 +1239,7 @@ static void print_request(struct drm_printer *m, x = print_sched_attr(rq->i915, &rq->sched.attr, buf, x, sizeof(buf)); - drm_printf(m, "%s%x%s [%llx:%x]%s @ %dms: %s\n", + drm_printf(m, "%s%x%s [%llx:%llx]%s @ %dms: %s\n", prefix, rq->global_seqno, i915_request_completed(rq) ? "!" : "", diff --git a/drivers/gpu/drm/vgem/vgem_fence.c b/drivers/gpu/drm/vgem/vgem_fence.c index c1c420afe2dd..eb17c0cd3727 100644 --- a/drivers/gpu/drm/vgem/vgem_fence.c +++ b/drivers/gpu/drm/vgem/vgem_fence.c @@ -53,13 +53,13 @@ static void vgem_fence_release(struct dma_fence *base) static void vgem_fence_value_str(struct dma_fence *fence, char *str, int size) { - snprintf(str, size, "%u", fence->seqno); + snprintf(str, size, "%llu", fence->seqno); } static void vgem_fence_timeline_value_str(struct dma_fence *fence, char *str, int size) { - snprintf(str, size, "%u", + snprintf(str, size, "%llu", dma_fence_is_signaled(fence) ? fence->seqno : 0); } diff --git a/include/linux/dma-fence.h b/include/linux/dma-fence.h index 999e4b104410..6b788467b2e3 100644 --- a/include/linux/dma-fence.h +++ b/include/linux/dma-fence.h @@ -77,7 +77,7 @@ struct dma_fence { struct list_head cb_list; spinlock_t *lock; u64 context; - unsigned seqno; + u64 seqno; unsigned long flags; ktime_t timestamp; int error; @@ -244,7 +244,7 @@ struct dma_fence_ops { }; void dma_fence_init(struct dma_fence *fence, const struct dma_fence_ops *ops, - spinlock_t *lock, u64 context, unsigned seqno); + spinlock_t *lock, u64 context, u64 seqno); void dma_fence_release(struct kref *kref); void dma_fence_free(struct dma_fence *fence); @@ -414,9 +414,17 @@ dma_fence_is_signaled(struct dma_fence *fence) * Returns true if f1 is chronologically later than f2. Both fences must be * from the same context, since a seqno is not common across contexts. */ -static inline bool __dma_fence_is_later(u32 f1, u32 f2) +static inline bool __dma_fence_is_later(u64 f1, u64 f2) { - return (int)(f1 - f2) > 0; + /* This is for backward compatibility with drivers which can only handle + * 32bit sequence numbers. Use a 64bit compare when any of the higher + * bits are none zero, otherwise use a 32bit compare with wrap around + * handling. + */ + if (upper_32_bits(f1) || upper_32_bits(f2)) + return f1 > f2; + + return (int)(lower_32_bits(f1) - lower_32_bits(f2)) > 0; } /** @@ -548,21 +556,21 @@ u64 dma_fence_context_alloc(unsigned num); do { \ struct dma_fence *__ff = (f); \ if (IS_ENABLED(CONFIG_DMA_FENCE_TRACE)) \ - pr_info("f %llu#%u: " fmt, \ + pr_info("f %llu#%llu: " fmt, \ __ff->context, __ff->seqno, ##args); \ } while (0) #define DMA_FENCE_WARN(f, fmt, args...) \ do { \ struct dma_fence *__ff = (f); \ - pr_warn("f %llu#%u: " fmt, __ff->context, __ff->seqno, \ + pr_warn("f %llu#%llu: " fmt, __ff->context, __ff->seqno,\ ##args); \ } while (0) #define DMA_FENCE_ERR(f, fmt, args...) \ do { \ struct dma_fence *__ff = (f); \ - pr_err("f %llu#%u: " fmt, __ff->context, __ff->seqno, \ + pr_err("f %llu#%llu: " fmt, __ff->context, __ff->seqno, \ ##args); \ } while (0) From dd847a7069747f1963962aee56a5694fbcc40caf Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Fri, 7 Dec 2018 14:34:28 +0200 Subject: [PATCH 04/49] drm/i915: Compile fix for 64b dma-fence seqno MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Many errs of the form: drivers/gpu/drm/i915/selftests/intel_hangcheck.c: In function ‘__igt_reset_evict_vma’: ./include/linux/kern_levels.h:5:18: error: format ‘%x’ expects argument of type ‘unsigned int’, but argum Fixes: b312d8ca3a7c ("dma-buf: make fence sequence numbers 64 bit v2") Cc: Christian König Cc: Chunming Zhou Cc: Chris Wilson Cc: Joonas Lahtinen Signed-off-by: Mika Kuoppala Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20181207123428.16257-1-mika.kuoppala@linux.intel.com --- drivers/gpu/drm/i915/i915_gem.c | 4 ++-- drivers/gpu/drm/i915/i915_gem_context.c | 8 ++++---- drivers/gpu/drm/i915/i915_request.c | 12 ++++++------ drivers/gpu/drm/i915/intel_lrc.c | 6 +++--- drivers/gpu/drm/i915/selftests/intel_hangcheck.c | 14 +++++++------- 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index c55b1f75c980..b70de1a9e899 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3187,7 +3187,7 @@ i915_gem_reset_request(struct intel_engine_cs *engine, */ if (i915_request_completed(request)) { - GEM_TRACE("%s pardoned global=%d (fence %llx:%d), current %d\n", + GEM_TRACE("%s pardoned global=%d (fence %llx:%lld), current %d\n", engine->name, request->global_seqno, request->fence.context, request->fence.seqno, intel_engine_get_seqno(engine)); @@ -3321,7 +3321,7 @@ static void nop_complete_submit_request(struct i915_request *request) { unsigned long flags; - GEM_TRACE("%s fence %llx:%d -> -EIO\n", + GEM_TRACE("%s fence %llx:%lld -> -EIO\n", request->engine->name, request->fence.context, request->fence.seqno); dma_fence_set_error(&request->fence, -EIO); diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index b97963db0287..66117a8281ef 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -653,7 +653,7 @@ last_request_on_engine(struct i915_timeline *timeline, rq = i915_gem_active_raw(&timeline->last_request, &engine->i915->drm.struct_mutex); if (rq && rq->engine == engine) { - GEM_TRACE("last request for %s on engine %s: %llx:%d\n", + GEM_TRACE("last request for %s on engine %s: %llx:%llu\n", timeline->name, engine->name, rq->fence.context, rq->fence.seqno); GEM_BUG_ON(rq->timeline != timeline); @@ -690,14 +690,14 @@ static bool engine_has_kernel_context_barrier(struct intel_engine_cs *engine) * switch-to-kernel-context? */ if (!i915_timeline_sync_is_later(barrier, &rq->fence)) { - GEM_TRACE("%s needs barrier for %llx:%d\n", + GEM_TRACE("%s needs barrier for %llx:%lld\n", ring->timeline->name, rq->fence.context, rq->fence.seqno); return false; } - GEM_TRACE("%s has barrier after %llx:%d\n", + GEM_TRACE("%s has barrier after %llx:%lld\n", ring->timeline->name, rq->fence.context, rq->fence.seqno); @@ -753,7 +753,7 @@ int i915_gem_switch_to_kernel_context(struct drm_i915_private *i915) if (prev->gem_context == i915->kernel_context) continue; - GEM_TRACE("add barrier on %s for %llx:%d\n", + GEM_TRACE("add barrier on %s for %llx:%lld\n", engine->name, prev->fence.context, prev->fence.seqno); diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index 71107540581d..191703986c7b 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -267,7 +267,7 @@ static void free_capture_list(struct i915_request *request) static void __retire_engine_request(struct intel_engine_cs *engine, struct i915_request *rq) { - GEM_TRACE("%s(%s) fence %llx:%d, global=%d, current %d\n", + GEM_TRACE("%s(%s) fence %llx:%lld, global=%d, current %d\n", __func__, engine->name, rq->fence.context, rq->fence.seqno, rq->global_seqno, @@ -329,7 +329,7 @@ static void i915_request_retire(struct i915_request *request) { struct i915_gem_active *active, *next; - GEM_TRACE("%s fence %llx:%d, global=%d, current %d\n", + GEM_TRACE("%s fence %llx:%lld, global=%d, current %d\n", request->engine->name, request->fence.context, request->fence.seqno, request->global_seqno, @@ -392,7 +392,7 @@ void i915_request_retire_upto(struct i915_request *rq) struct intel_ring *ring = rq->ring; struct i915_request *tmp; - GEM_TRACE("%s fence %llx:%d, global=%d, current %d\n", + GEM_TRACE("%s fence %llx:%lld, global=%d, current %d\n", rq->engine->name, rq->fence.context, rq->fence.seqno, rq->global_seqno, @@ -433,7 +433,7 @@ void __i915_request_submit(struct i915_request *request) struct intel_engine_cs *engine = request->engine; u32 seqno; - GEM_TRACE("%s fence %llx:%d -> global=%d, current %d\n", + GEM_TRACE("%s fence %llx:%lld -> global=%d, current %d\n", engine->name, request->fence.context, request->fence.seqno, engine->timeline.seqno + 1, @@ -483,7 +483,7 @@ void __i915_request_unsubmit(struct i915_request *request) { struct intel_engine_cs *engine = request->engine; - GEM_TRACE("%s fence %llx:%d <- global=%d, current %d\n", + GEM_TRACE("%s fence %llx:%lld <- global=%d, current %d\n", engine->name, request->fence.context, request->fence.seqno, request->global_seqno, @@ -958,7 +958,7 @@ void i915_request_add(struct i915_request *request) struct i915_request *prev; u32 *cs; - GEM_TRACE("%s fence %llx:%d\n", + GEM_TRACE("%s fence %llx:%lld\n", engine->name, request->fence.context, request->fence.seqno); lockdep_assert_held(&request->i915->drm.struct_mutex); diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 08fd9b12e4d7..9399db3260ad 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -450,7 +450,7 @@ static void execlists_submit_ports(struct intel_engine_cs *engine) desc = execlists_update_context(rq); GEM_DEBUG_EXEC(port[n].context_id = upper_32_bits(desc)); - GEM_TRACE("%s in[%d]: ctx=%d.%d, global=%d (fence %llx:%d) (current %d), prio=%d\n", + GEM_TRACE("%s in[%d]: ctx=%d.%d, global=%d (fence %llx:%lld) (current %d), prio=%d\n", engine->name, n, port[n].context_id, count, rq->global_seqno, @@ -743,7 +743,7 @@ execlists_cancel_port_requests(struct intel_engine_execlists * const execlists) while (num_ports-- && port_isset(port)) { struct i915_request *rq = port_request(port); - GEM_TRACE("%s:port%u global=%d (fence %llx:%d), (current %d)\n", + GEM_TRACE("%s:port%u global=%d (fence %llx:%lld), (current %d)\n", rq->engine->name, (unsigned int)(port - execlists->port), rq->global_seqno, @@ -952,7 +952,7 @@ static void process_csb(struct intel_engine_cs *engine) EXECLISTS_ACTIVE_USER)); rq = port_unpack(port, &count); - GEM_TRACE("%s out[0]: ctx=%d.%d, global=%d (fence %llx:%d) (current %d), prio=%d\n", + GEM_TRACE("%s out[0]: ctx=%d.%d, global=%d (fence %llx:%lld) (current %d), prio=%d\n", engine->name, port->context_id, count, rq ? rq->global_seqno : 0, diff --git a/drivers/gpu/drm/i915/selftests/intel_hangcheck.c b/drivers/gpu/drm/i915/selftests/intel_hangcheck.c index defe671130ab..33494d922fab 100644 --- a/drivers/gpu/drm/i915/selftests/intel_hangcheck.c +++ b/drivers/gpu/drm/i915/selftests/intel_hangcheck.c @@ -478,7 +478,7 @@ static int __igt_reset_engine(struct drm_i915_private *i915, bool active) if (!wait_until_running(&h, rq)) { struct drm_printer p = drm_info_printer(i915->drm.dev); - pr_err("%s: Failed to start request %x, at %x\n", + pr_err("%s: Failed to start request %llx, at %x\n", __func__, rq->fence.seqno, hws_seqno(&h, rq)); intel_engine_dump(engine, &p, "%s\n", engine->name); @@ -579,7 +579,7 @@ static int active_request_put(struct i915_request *rq) return 0; if (i915_request_wait(rq, 0, 5 * HZ) < 0) { - GEM_TRACE("%s timed out waiting for completion of fence %llx:%d, seqno %d.\n", + GEM_TRACE("%s timed out waiting for completion of fence %llx:%lld, seqno %d.\n", rq->engine->name, rq->fence.context, rq->fence.seqno, @@ -756,7 +756,7 @@ static int __igt_reset_engines(struct drm_i915_private *i915, if (!wait_until_running(&h, rq)) { struct drm_printer p = drm_info_printer(i915->drm.dev); - pr_err("%s: Failed to start request %x, at %x\n", + pr_err("%s: Failed to start request %llx, at %x\n", __func__, rq->fence.seqno, hws_seqno(&h, rq)); intel_engine_dump(engine, &p, "%s\n", engine->name); @@ -955,7 +955,7 @@ static int igt_reset_wait(void *arg) if (!wait_until_running(&h, rq)) { struct drm_printer p = drm_info_printer(i915->drm.dev); - pr_err("%s: Failed to start request %x, at %x\n", + pr_err("%s: Failed to start request %llx, at %x\n", __func__, rq->fence.seqno, hws_seqno(&h, rq)); intel_engine_dump(rq->engine, &p, "%s\n", rq->engine->name); @@ -1134,7 +1134,7 @@ static int __igt_reset_evict_vma(struct drm_i915_private *i915, if (!wait_until_running(&h, rq)) { struct drm_printer p = drm_info_printer(i915->drm.dev); - pr_err("%s: Failed to start request %x, at %x\n", + pr_err("%s: Failed to start request %llx, at %x\n", __func__, rq->fence.seqno, hws_seqno(&h, rq)); intel_engine_dump(rq->engine, &p, "%s\n", rq->engine->name); @@ -1329,7 +1329,7 @@ static int igt_reset_queue(void *arg) if (!wait_until_running(&h, prev)) { struct drm_printer p = drm_info_printer(i915->drm.dev); - pr_err("%s(%s): Failed to start request %x, at %x\n", + pr_err("%s(%s): Failed to start request %llx, at %x\n", __func__, engine->name, prev->fence.seqno, hws_seqno(&h, prev)); intel_engine_dump(engine, &p, @@ -1440,7 +1440,7 @@ static int igt_handle_error(void *arg) if (!wait_until_running(&h, rq)) { struct drm_printer p = drm_info_printer(i915->drm.dev); - pr_err("%s: Failed to start request %x, at %x\n", + pr_err("%s: Failed to start request %llx, at %x\n", __func__, rq->fence.seqno, hws_seqno(&h, rq)); intel_engine_dump(rq->engine, &p, "%s\n", rq->engine->name); From 36e7999dc19a1a6e76258020a49f7f7836018e46 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 3 Dec 2018 14:24:33 -0800 Subject: [PATCH 05/49] drm/v3d: Document cache flushing ABI. Right now, userspace doesn't do any L2T writes, but we should lay out our expectations for how it works. v2: Explicitly mention the VCD cache flushing requirements and that we'll flush the other caches before each of the CLs. Signed-off-by: Eric Anholt Link: https://patchwork.freedesktop.org/patch/msgid/20181203222438.25417-1-eric@anholt.net Reviewed-by: Dave Emett --- include/uapi/drm/v3d_drm.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/uapi/drm/v3d_drm.h b/include/uapi/drm/v3d_drm.h index 35c7d813c66e..ea70669d2138 100644 --- a/include/uapi/drm/v3d_drm.h +++ b/include/uapi/drm/v3d_drm.h @@ -52,6 +52,14 @@ extern "C" { * * This asks the kernel to have the GPU execute an optional binner * command list, and a render command list. + * + * The L1T, slice, L2C, L2T, and GCA caches will be flushed before + * each CL executes. The VCD cache should be flushed (if necessary) + * by the submitted CLs. The TLB writes are guaranteed to have been + * flushed by the time the render done IRQ happens, which is the + * trigger for out_sync. Any dirtying of cachelines by the job (only + * possible using TMU writes) must be flushed by the caller using the + * CL's cache flush commands. */ struct drm_v3d_submit_cl { /* Pointer to the binner command list. From 2aa34fd5c7754824cf5488b61ac644f30d3c5c85 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 3 Dec 2018 14:24:34 -0800 Subject: [PATCH 06/49] drm/v3d: Drop unused v3d_flush_caches(). Now that I've specified how the end-of-pipeline flushing should work, we're never going to use this function. Signed-off-by: Eric Anholt Reviewed-by: Dave Emett Link: https://patchwork.freedesktop.org/patch/msgid/20181203222438.25417-2-eric@anholt.net --- drivers/gpu/drm/v3d/v3d_drv.h | 1 - drivers/gpu/drm/v3d/v3d_gem.c | 21 --------------------- 2 files changed, 22 deletions(-) diff --git a/drivers/gpu/drm/v3d/v3d_drv.h b/drivers/gpu/drm/v3d/v3d_drv.h index dcb772a19191..fdda3037f7af 100644 --- a/drivers/gpu/drm/v3d/v3d_drv.h +++ b/drivers/gpu/drm/v3d/v3d_drv.h @@ -308,7 +308,6 @@ void v3d_exec_put(struct v3d_exec_info *exec); void v3d_tfu_job_put(struct v3d_tfu_job *exec); void v3d_reset(struct v3d_dev *v3d); void v3d_invalidate_caches(struct v3d_dev *v3d); -void v3d_flush_caches(struct v3d_dev *v3d); /* v3d_irq.c */ void v3d_irq_init(struct v3d_dev *v3d); diff --git a/drivers/gpu/drm/v3d/v3d_gem.c b/drivers/gpu/drm/v3d/v3d_gem.c index 05ca6319065e..dec94dc89659 100644 --- a/drivers/gpu/drm/v3d/v3d_gem.c +++ b/drivers/gpu/drm/v3d/v3d_gem.c @@ -175,20 +175,6 @@ v3d_invalidate_slices(struct v3d_dev *v3d, int core) V3D_SET_FIELD(0xf, V3D_SLCACTL_ICC)); } -/* Invalidates texture L2 cachelines */ -static void -v3d_invalidate_l2t(struct v3d_dev *v3d, int core) -{ - V3D_CORE_WRITE(core, - V3D_CTL_L2TCACTL, - V3D_L2TCACTL_L2TFLS | - V3D_SET_FIELD(V3D_L2TCACTL_FLM_CLEAR, V3D_L2TCACTL_FLM)); - if (wait_for(!(V3D_CORE_READ(core, V3D_CTL_L2TCACTL) & - V3D_L2TCACTL_L2TFLS), 100)) { - DRM_ERROR("Timeout waiting for L2T invalidate\n"); - } -} - void v3d_invalidate_caches(struct v3d_dev *v3d) { @@ -199,13 +185,6 @@ v3d_invalidate_caches(struct v3d_dev *v3d) v3d_flush_l2t(v3d, 0); } -void -v3d_flush_caches(struct v3d_dev *v3d) -{ - v3d_invalidate_l1td(v3d, 0); - v3d_invalidate_l2t(v3d, 0); -} - static void v3d_attach_object_fences(struct v3d_bo **bos, int bo_count, struct dma_fence *fence) From 2e6dc3bd80478212e84addf1cafd6ec60674b884 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 3 Dec 2018 14:24:35 -0800 Subject: [PATCH 07/49] drm/v3d: Don't bother flushing L1TD at job start. This is the write combiner for TMU writes. You're supposed to flush that at job end if you had dirtied any cachelines. Flushing it at job start then doesn't make any sense. Signed-off-by: Eric Anholt Fixes: 57692c94dcbe ("drm/v3d: Introduce a new DRM driver for Broadcom V3D V3.x+") Reviewed-by: Dave Emett Link: https://patchwork.freedesktop.org/patch/msgid/20181203222438.25417-3-eric@anholt.net --- drivers/gpu/drm/v3d/v3d_gem.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/drivers/gpu/drm/v3d/v3d_gem.c b/drivers/gpu/drm/v3d/v3d_gem.c index dec94dc89659..f82c1ccfaeed 100644 --- a/drivers/gpu/drm/v3d/v3d_gem.c +++ b/drivers/gpu/drm/v3d/v3d_gem.c @@ -139,22 +139,10 @@ v3d_invalidate_l2(struct v3d_dev *v3d, int core) V3D_L2CACTL_L2CENA); } -static void -v3d_invalidate_l1td(struct v3d_dev *v3d, int core) -{ - V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL, V3D_L2TCACTL_TMUWCF); - if (wait_for(!(V3D_CORE_READ(core, V3D_CTL_L2TCACTL) & - V3D_L2TCACTL_L2TFLS), 100)) { - DRM_ERROR("Timeout waiting for L1T write combiner flush\n"); - } -} - /* Invalidates texture L2 cachelines */ static void v3d_flush_l2t(struct v3d_dev *v3d, int core) { - v3d_invalidate_l1td(v3d, core); - V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL, V3D_L2TCACTL_L2TFLS | V3D_SET_FIELD(V3D_L2TCACTL_FLM_FLUSH, V3D_L2TCACTL_FLM)); From 51c1b6f9eb3dbdec91b0e3c89f623e634c996bbb Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 3 Dec 2018 14:24:36 -0800 Subject: [PATCH 08/49] drm/v3d: Drop the wait for L2T flush to complete. According to Dave, once you've started an L2T flush, all L2T accesses will be blocked until the flush completes. This fixes a consistent 3-4ms stall between the ioctl and running the job, and 3DMMES Taiji goes from 27fps to 110fps. v2: Leave a note about why we don't need to wait for completion. Signed-off-by: Eric Anholt Fixes: 57692c94dcbe ("drm/v3d: Introduce a new DRM driver for Broadcom V3D V3.x+") Reviewed-by: Dave Emett Link: https://patchwork.freedesktop.org/patch/msgid/20181203222438.25417-4-eric@anholt.net --- drivers/gpu/drm/v3d/v3d_gem.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/v3d/v3d_gem.c b/drivers/gpu/drm/v3d/v3d_gem.c index f82c1ccfaeed..2b378de23fbd 100644 --- a/drivers/gpu/drm/v3d/v3d_gem.c +++ b/drivers/gpu/drm/v3d/v3d_gem.c @@ -143,13 +143,13 @@ v3d_invalidate_l2(struct v3d_dev *v3d, int core) static void v3d_flush_l2t(struct v3d_dev *v3d, int core) { + /* While there is a busy bit (V3D_L2TCACTL_L2TFLS), we don't + * need to wait for completion before dispatching the job -- + * L2T accesses will be stalled until the flush has completed. + */ V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL, V3D_L2TCACTL_L2TFLS | V3D_SET_FIELD(V3D_L2TCACTL_FLM_FLUSH, V3D_L2TCACTL_FLM)); - if (wait_for(!(V3D_CORE_READ(core, V3D_CTL_L2TCACTL) & - V3D_L2TCACTL_L2TFLS), 100)) { - DRM_ERROR("Timeout waiting for L2T flush\n"); - } } /* Invalidates the slice caches. These are read-only caches. */ From 7b9d2fe4350a9c12f66ad8cc78c1098226f6c3c2 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 3 Dec 2018 14:24:37 -0800 Subject: [PATCH 09/49] drm/v3d: Stop trying to flush L2C on V3D 3.3+ This cache was replaced with the slice accessing the L2T in the newer generations. Noted by Dave during review. Signed-off-by: Eric Anholt Link: https://patchwork.freedesktop.org/patch/msgid/20181203222438.25417-5-eric@anholt.net Reviewed-by: Dave Emett --- drivers/gpu/drm/v3d/v3d_gem.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/v3d/v3d_gem.c b/drivers/gpu/drm/v3d/v3d_gem.c index 2b378de23fbd..06525ea9ec50 100644 --- a/drivers/gpu/drm/v3d/v3d_gem.c +++ b/drivers/gpu/drm/v3d/v3d_gem.c @@ -130,10 +130,15 @@ v3d_flush_l3(struct v3d_dev *v3d) } } -/* Invalidates the (read-only) L2 cache. */ +/* Invalidates the (read-only) L2C cache. This was the L2 cache for + * uniforms and instructions on V3D 3.2. + */ static void -v3d_invalidate_l2(struct v3d_dev *v3d, int core) +v3d_invalidate_l2c(struct v3d_dev *v3d, int core) { + if (v3d->ver > 32) + return; + V3D_CORE_WRITE(core, V3D_CTL_L2CACTL, V3D_L2CACTL_L2CCLR | V3D_L2CACTL_L2CENA); @@ -168,7 +173,7 @@ v3d_invalidate_caches(struct v3d_dev *v3d) { v3d_flush_l3(v3d); - v3d_invalidate_l2(v3d, 0); + v3d_invalidate_l2c(v3d, 0); v3d_invalidate_slices(v3d, 0); v3d_flush_l2t(v3d, 0); } From aa5beec32e8b78bfcf621e3c3daebfb1644b6365 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 3 Dec 2018 14:24:38 -0800 Subject: [PATCH 10/49] drm/v3d: Invalidate the caches from the outside in. This would be a fairly obscure race, but let's make sure we don't ever lose it. Signed-off-by: Eric Anholt Link: https://patchwork.freedesktop.org/patch/msgid/20181203222438.25417-6-eric@anholt.net Reviewed-by: Dave Emett --- drivers/gpu/drm/v3d/v3d_gem.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/v3d/v3d_gem.c b/drivers/gpu/drm/v3d/v3d_gem.c index 06525ea9ec50..803f31467ec1 100644 --- a/drivers/gpu/drm/v3d/v3d_gem.c +++ b/drivers/gpu/drm/v3d/v3d_gem.c @@ -171,11 +171,15 @@ v3d_invalidate_slices(struct v3d_dev *v3d, int core) void v3d_invalidate_caches(struct v3d_dev *v3d) { + /* Invalidate the caches from the outside in. That way if + * another CL's concurrent use of nearby memory were to pull + * an invalidated cacheline back in, we wouldn't leave stale + * data in the inner cache. + */ v3d_flush_l3(v3d); - v3d_invalidate_l2c(v3d, 0); - v3d_invalidate_slices(v3d, 0); v3d_flush_l2t(v3d, 0); + v3d_invalidate_slices(v3d, 0); } static void From 8e75d582db02bcb171d65ec71eecbd3072a5fd3a Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 7 Dec 2018 09:36:05 +0100 Subject: [PATCH 11/49] drm/vc4: Fix negative X/Y positioning on SAND planes Commit 3e407417b192 ("drm/vc4: Fix X/Y positioning of planes using T_TILES modifier") fixed the problem with T_TILES format, but left things in a non-working state for SAND formats. Address that now. Signed-off-by: Boris Brezillon Reviewed-by: Eric Anholt Link: https://patchwork.freedesktop.org/patch/msgid/20181207083606.15449-1-boris.brezillon@bootlin.com --- drivers/gpu/drm/vc4/vc4_plane.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index 75db62cbe468..fb1214b91a25 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -595,6 +595,7 @@ static int vc4_plane_mode_set(struct drm_plane *plane, case DRM_FORMAT_MOD_BROADCOM_SAND128: case DRM_FORMAT_MOD_BROADCOM_SAND256: { uint32_t param = fourcc_mod_broadcom_param(fb->modifier); + u32 tile_w, tile, x_off, pix_per_tile; /* Column-based NV12 or RGBA. */ @@ -614,12 +615,15 @@ static int vc4_plane_mode_set(struct drm_plane *plane, switch (base_format_mod) { case DRM_FORMAT_MOD_BROADCOM_SAND64: tiling = SCALER_CTL0_TILING_64B; + tile_w = 64; break; case DRM_FORMAT_MOD_BROADCOM_SAND128: tiling = SCALER_CTL0_TILING_128B; + tile_w = 128; break; case DRM_FORMAT_MOD_BROADCOM_SAND256: tiling = SCALER_CTL0_TILING_256B_OR_T; + tile_w = 256; break; default: break; @@ -630,6 +634,23 @@ static int vc4_plane_mode_set(struct drm_plane *plane, return -EINVAL; } + pix_per_tile = tile_w / fb->format->cpp[0]; + tile = vc4_state->src_x / pix_per_tile; + x_off = vc4_state->src_x % pix_per_tile; + + /* Adjust the base pointer to the first pixel to be scanned + * out. + */ + for (i = 0; i < num_planes; i++) { + vc4_state->offsets[i] += param * tile_w * tile; + vc4_state->offsets[i] += vc4_state->src_y / + (i ? v_subsample : 1) * + tile_w; + vc4_state->offsets[i] += x_off / + (i ? h_subsample : 1) * + fb->format->cpp[i]; + } + pitch0 = VC4_SET_FIELD(param, SCALER_TILE_HEIGHT); break; } From 7cd3cf3540a37072c647b8b5120a80de5bb3d199 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 7 Dec 2018 09:36:06 +0100 Subject: [PATCH 12/49] drm/vc4: Add support for X/Y reflection Add support for X/Y reflection when the plane is using linear or T-tiled formats. X/Y reflection hasn't been tested on SAND formats, so we reject them until proper testing/debugging has been done. Signed-off-by: Boris Brezillon Reviewed-by: Eric Anholt Link: https://patchwork.freedesktop.org/patch/msgid/20181207083606.15449-2-boris.brezillon@bootlin.com --- drivers/gpu/drm/vc4/vc4_plane.c | 59 ++++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index fb1214b91a25..283abd7d1e9b 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -492,8 +492,9 @@ static int vc4_plane_mode_set(struct drm_plane *plane, bool mix_plane_alpha; bool covers_screen; u32 scl0, scl1, pitch0; - u32 tiling; + u32 tiling, src_y; u32 hvs_format = format->hvs; + unsigned int rotation; int ret, i; if (vc4_state->dlist_initialized) @@ -520,6 +521,16 @@ static int vc4_plane_mode_set(struct drm_plane *plane, h_subsample = drm_format_horz_chroma_subsampling(format->drm); v_subsample = drm_format_vert_chroma_subsampling(format->drm); + rotation = drm_rotation_simplify(state->rotation, + DRM_MODE_ROTATE_0 | + DRM_MODE_REFLECT_X | + DRM_MODE_REFLECT_Y); + + /* We must point to the last line when Y reflection is enabled. */ + src_y = vc4_state->src_y; + if (rotation & DRM_MODE_REFLECT_Y) + src_y += vc4_state->src_h[0] - 1; + switch (base_format_mod) { case DRM_FORMAT_MOD_LINEAR: tiling = SCALER_CTL0_TILING_LINEAR; @@ -529,9 +540,10 @@ static int vc4_plane_mode_set(struct drm_plane *plane, * out. */ for (i = 0; i < num_planes; i++) { - vc4_state->offsets[i] += vc4_state->src_y / + vc4_state->offsets[i] += src_y / (i ? v_subsample : 1) * fb->pitches[i]; + vc4_state->offsets[i] += vc4_state->src_x / (i ? h_subsample : 1) * fb->format->cpp[i]; @@ -557,22 +569,38 @@ static int vc4_plane_mode_set(struct drm_plane *plane, u32 tiles_w = fb->pitches[0] >> (tile_size_shift - tile_h_shift); u32 tiles_l = vc4_state->src_x >> tile_w_shift; u32 tiles_r = tiles_w - tiles_l; - u32 tiles_t = vc4_state->src_y >> tile_h_shift; + u32 tiles_t = src_y >> tile_h_shift; /* Intra-tile offsets, which modify the base address (the * SCALER_PITCH0_TILE_Y_OFFSET tells HVS how to walk from that * base address). */ - u32 tile_y = (vc4_state->src_y >> 4) & 1; - u32 subtile_y = (vc4_state->src_y >> 2) & 3; - u32 utile_y = vc4_state->src_y & 3; + u32 tile_y = (src_y >> 4) & 1; + u32 subtile_y = (src_y >> 2) & 3; + u32 utile_y = src_y & 3; u32 x_off = vc4_state->src_x & tile_w_mask; - u32 y_off = vc4_state->src_y & tile_h_mask; + u32 y_off = src_y & tile_h_mask; + + /* When Y reflection is requested we must set the + * SCALER_PITCH0_TILE_LINE_DIR flag to tell HVS that all lines + * after the initial one should be fetched in descending order, + * which makes sense since we start from the last line and go + * backward. + * Don't know why we need y_off = max_y_off - y_off, but it's + * definitely required (I guess it's also related to the "going + * backward" situation). + */ + if (rotation & DRM_MODE_REFLECT_Y) { + y_off = tile_h_mask - y_off; + pitch0 = SCALER_PITCH0_TILE_LINE_DIR; + } else { + pitch0 = 0; + } tiling = SCALER_CTL0_TILING_256B_OR_T; - pitch0 = (VC4_SET_FIELD(x_off, SCALER_PITCH0_SINK_PIX) | - VC4_SET_FIELD(y_off, SCALER_PITCH0_TILE_Y_OFFSET) | - VC4_SET_FIELD(tiles_l, SCALER_PITCH0_TILE_WIDTH_L) | - VC4_SET_FIELD(tiles_r, SCALER_PITCH0_TILE_WIDTH_R)); + pitch0 |= (VC4_SET_FIELD(x_off, SCALER_PITCH0_SINK_PIX) | + VC4_SET_FIELD(y_off, SCALER_PITCH0_TILE_Y_OFFSET) | + VC4_SET_FIELD(tiles_l, SCALER_PITCH0_TILE_WIDTH_L) | + VC4_SET_FIELD(tiles_r, SCALER_PITCH0_TILE_WIDTH_R)); vc4_state->offsets[0] += tiles_t * (tiles_w << tile_size_shift); vc4_state->offsets[0] += subtile_y << 8; vc4_state->offsets[0] += utile_y << 4; @@ -643,7 +671,7 @@ static int vc4_plane_mode_set(struct drm_plane *plane, */ for (i = 0; i < num_planes; i++) { vc4_state->offsets[i] += param * tile_w * tile; - vc4_state->offsets[i] += vc4_state->src_y / + vc4_state->offsets[i] += src_y / (i ? v_subsample : 1) * tile_w; vc4_state->offsets[i] += x_off / @@ -664,6 +692,8 @@ static int vc4_plane_mode_set(struct drm_plane *plane, /* Control word */ vc4_dlist_write(vc4_state, SCALER_CTL0_VALID | + (rotation & DRM_MODE_REFLECT_X ? SCALER_CTL0_HFLIP : 0) | + (rotation & DRM_MODE_REFLECT_Y ? SCALER_CTL0_VFLIP : 0) | VC4_SET_FIELD(SCALER_CTL0_RGBA_EXPAND_ROUND, SCALER_CTL0_RGBA_EXPAND) | (format->pixel_order << SCALER_CTL0_ORDER_SHIFT) | (hvs_format << SCALER_CTL0_PIXEL_FORMAT_SHIFT) | @@ -1144,6 +1174,11 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev, drm_plane_helper_add(plane, &vc4_plane_helper_funcs); drm_plane_create_alpha_property(plane); + drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0, + DRM_MODE_ROTATE_0 | + DRM_MODE_ROTATE_180 | + DRM_MODE_REFLECT_X | + DRM_MODE_REFLECT_Y); return plane; } From 16bff572cc660f19e58c99941368dea050b36a05 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 28 Nov 2018 23:12:34 +0100 Subject: [PATCH 13/49] drm/dp-mst-helper: Remove hotplug callback When everyone implements it exactly the same way, among all 4 implementations, there's not really a need to overwrite this at all. Aside: drm_kms_helper_hotplug_event is pretty much core functionality at this point. Probably should move it there. Reviewed-by: Lyude Paul Acked-by: Alex Deucher Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20181128221234.15054-1-daniel.vetter@ffwll.ch --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 9 --------- drivers/gpu/drm/drm_dp_mst_topology.c | 7 ++++--- drivers/gpu/drm/i915/intel_dp_mst.c | 10 ---------- drivers/gpu/drm/nouveau/dispnv50/disp.c | 8 -------- drivers/gpu/drm/radeon/radeon_dp_mst.c | 9 --------- include/drm/drm_dp_mst_helper.h | 2 -- 6 files changed, 4 insertions(+), 41 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index d02c32a1039c..9fdeca096407 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -396,14 +396,6 @@ static void dm_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr, drm_connector_put(connector); } -static void dm_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr) -{ - struct amdgpu_dm_connector *master = container_of(mgr, struct amdgpu_dm_connector, mst_mgr); - struct drm_device *dev = master->base.dev; - - drm_kms_helper_hotplug_event(dev); -} - static void dm_dp_mst_register_connector(struct drm_connector *connector) { struct drm_device *dev = connector->dev; @@ -420,7 +412,6 @@ static void dm_dp_mst_register_connector(struct drm_connector *connector) static const struct drm_dp_mst_topology_cbs dm_mst_cbs = { .add_connector = dm_dp_add_mst_connector, .destroy_connector = dm_dp_destroy_mst_connector, - .hotplug = dm_dp_mst_hotplug, .register_connector = dm_dp_mst_register_connector }; diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 529414556962..a9b684f14d14 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -33,6 +33,7 @@ #include #include #include +#include /** * DOC: dp mst helper @@ -1639,7 +1640,7 @@ static void drm_dp_send_link_address(struct drm_dp_mst_topology_mgr *mgr, for (i = 0; i < txmsg->reply.u.link_addr.nports; i++) { drm_dp_add_port(mstb, mgr->dev, &txmsg->reply.u.link_addr.ports[i]); } - (*mgr->cbs->hotplug)(mgr); + drm_kms_helper_hotplug_event(mgr->dev); } } else { mstb->link_address_sent = false; @@ -2412,7 +2413,7 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr) drm_dp_update_port(mstb, &msg.u.conn_stat); DRM_DEBUG_KMS("Got CSN: pn: %d ldps:%d ddps: %d mcs: %d ip: %d pdt: %d\n", msg.u.conn_stat.port_number, msg.u.conn_stat.legacy_device_plug_status, msg.u.conn_stat.displayport_device_plug_status, msg.u.conn_stat.message_capability_status, msg.u.conn_stat.input_port, msg.u.conn_stat.peer_device_type); - (*mgr->cbs->hotplug)(mgr); + drm_kms_helper_hotplug_event(mgr->dev); } else if (msg.req_type == DP_RESOURCE_STATUS_NOTIFY) { drm_dp_send_up_ack_reply(mgr, mgr->mst_primary, msg.req_type, seqno, false); @@ -3109,7 +3110,7 @@ static void drm_dp_destroy_connector_work(struct work_struct *work) send_hotplug = true; } if (send_hotplug) - (*mgr->cbs->hotplug)(mgr); + drm_kms_helper_hotplug_event(mgr->dev); } static struct drm_private_state * diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index 4de247ddf05f..f05427b74e34 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c @@ -517,20 +517,10 @@ static void intel_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr, drm_connector_put(connector); } -static void intel_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr) -{ - struct intel_dp *intel_dp = container_of(mgr, struct intel_dp, mst_mgr); - struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); - struct drm_device *dev = intel_dig_port->base.base.dev; - - drm_kms_helper_hotplug_event(dev); -} - static const struct drm_dp_mst_topology_cbs mst_cbs = { .add_connector = intel_dp_add_mst_connector, .register_connector = intel_dp_register_mst_connector, .destroy_connector = intel_dp_destroy_mst_connector, - .hotplug = intel_dp_mst_hotplug, }; static struct intel_dp_mst_encoder * diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 6cbbae3f438b..4a56841958c8 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -1055,13 +1055,6 @@ nv50_mstm_prepare(struct nv50_mstm *mstm) } } -static void -nv50_mstm_hotplug(struct drm_dp_mst_topology_mgr *mgr) -{ - struct nv50_mstm *mstm = nv50_mstm(mgr); - drm_kms_helper_hotplug_event(mstm->outp->base.base.dev); -} - static void nv50_mstm_destroy_connector(struct drm_dp_mst_topology_mgr *mgr, struct drm_connector *connector) @@ -1113,7 +1106,6 @@ nv50_mstm = { .add_connector = nv50_mstm_add_connector, .register_connector = nv50_mstm_register_connector, .destroy_connector = nv50_mstm_destroy_connector, - .hotplug = nv50_mstm_hotplug, }; void diff --git a/drivers/gpu/drm/radeon/radeon_dp_mst.c b/drivers/gpu/drm/radeon/radeon_dp_mst.c index 84b3ad2172a3..a0c70e27ab65 100644 --- a/drivers/gpu/drm/radeon/radeon_dp_mst.c +++ b/drivers/gpu/drm/radeon/radeon_dp_mst.c @@ -320,19 +320,10 @@ static void radeon_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr, DRM_DEBUG_KMS("\n"); } -static void radeon_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr) -{ - struct radeon_connector *master = container_of(mgr, struct radeon_connector, mst_mgr); - struct drm_device *dev = master->base.dev; - - drm_kms_helper_hotplug_event(dev); -} - static const struct drm_dp_mst_topology_cbs mst_cbs = { .add_connector = radeon_dp_add_mst_connector, .register_connector = radeon_dp_register_mst_connector, .destroy_connector = radeon_dp_destroy_mst_connector, - .hotplug = radeon_dp_mst_hotplug, }; static struct diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h index 59f005b419cf..371cc2816477 100644 --- a/include/drm/drm_dp_mst_helper.h +++ b/include/drm/drm_dp_mst_helper.h @@ -387,8 +387,6 @@ struct drm_dp_mst_topology_cbs { void (*register_connector)(struct drm_connector *connector); void (*destroy_connector)(struct drm_dp_mst_topology_mgr *mgr, struct drm_connector *connector); - void (*hotplug)(struct drm_dp_mst_topology_mgr *mgr); - }; #define DP_MAX_PAYLOAD (sizeof(unsigned long) * 8) From 32658d2c8073699473c28b67f14ad51403ccec5d Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 8 Dec 2018 08:36:25 +0000 Subject: [PATCH 14/49] drm/ast: Remove set but not used variable 'bo' Fixes gcc '-Wunused-but-set-variable' warning: drivers/gpu/drm/ast/ast_fb.c: In function 'astfb_create': drivers/gpu/drm/ast/ast_fb.c:194:17: warning: variable 'bo' set but not used [-Wunused-but-set-variable] It never used since introduction in commit 312fec1405dd ("drm: Initial KMS driver for AST (ASpeed Technologies) 2000 series (v2)") Signed-off-by: YueHaibing Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/1544258185-50430-1-git-send-email-yuehaibing@huawei.com --- drivers/gpu/drm/ast/ast_fb.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/ast/ast_fb.c b/drivers/gpu/drm/ast/ast_fb.c index 0cd827e11fa2..a80bca1a857f 100644 --- a/drivers/gpu/drm/ast/ast_fb.c +++ b/drivers/gpu/drm/ast/ast_fb.c @@ -191,7 +191,6 @@ static int astfb_create(struct drm_fb_helper *helper, int size, ret; void *sysram; struct drm_gem_object *gobj = NULL; - struct ast_bo *bo = NULL; mode_cmd.width = sizes->surface_width; mode_cmd.height = sizes->surface_height; mode_cmd.pitches[0] = mode_cmd.width * ((sizes->surface_bpp + 7)/8); @@ -206,7 +205,6 @@ static int astfb_create(struct drm_fb_helper *helper, DRM_ERROR("failed to create fbcon backing object %d\n", ret); return ret; } - bo = gem_to_ast_bo(gobj); sysram = vmalloc(size); if (!sysram) From c978ae9bde582e82a04c63a4071701691dd8b35c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 28 Sep 2018 21:03:59 +0300 Subject: [PATCH 15/49] drm/dp/mst: Configure no_stop_bit correctly for remote i2c xfers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We aren't supposed to force a stop+start between every i2c msg when performing multi message transfers. This should eg. cause the DDC segment address to be reset back to 0 between writing the segment address and reading the actual EDID extension block. To quote the E-DDC spec: "... this standard requires that the segment pointer be reset to 00h when a NO ACK or a STOP condition is received." Since we're going to touch this might as well consult the I2C_M_STOP flag to determine whether we want to force the stop or not. Cc: Brian Vincent References: https://bugs.freedesktop.org/show_bug.cgi?id=108081 Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20180928180403.22499-1-ville.syrjala@linux.intel.com Reviewed-by: Dhinakaran Pandiyan --- drivers/gpu/drm/drm_dp_mst_topology.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index a9b684f14d14..229ad6026314 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -3287,6 +3287,7 @@ static int drm_dp_mst_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs msg.u.i2c_read.transactions[i].i2c_dev_id = msgs[i].addr; msg.u.i2c_read.transactions[i].num_bytes = msgs[i].len; msg.u.i2c_read.transactions[i].bytes = msgs[i].buf; + msg.u.i2c_read.transactions[i].no_stop_bit = !(msgs[i].flags & I2C_M_STOP); } msg.u.i2c_read.read_i2c_device_id = msgs[num - 1].addr; msg.u.i2c_read.num_bytes_read = msgs[num - 1].len; From cb8ce7111117e16a87f3f55c014ccd1f19f81016 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 28 Sep 2018 21:04:00 +0300 Subject: [PATCH 16/49] drm/dp/mst: Validate REMOTE_I2C_READ harder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make sure i2c msgs we're asked to transfer conform to the requirements of REMOTE_I2C_READ. We were only checking that the last message is a read, but we must also check that the preceding messages are all writes. Also check that the length of each message isn't too long. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20180928180403.22499-2-ville.syrjala@linux.intel.com Reviewed-by: Dhinakaran Pandiyan --- drivers/gpu/drm/drm_dp_mst_topology.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 229ad6026314..f0cbd5fad8fc 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -3250,6 +3250,23 @@ void drm_dp_mst_topology_mgr_destroy(struct drm_dp_mst_topology_mgr *mgr) } EXPORT_SYMBOL(drm_dp_mst_topology_mgr_destroy); +static bool remote_i2c_read_ok(const struct i2c_msg msgs[], int num) +{ + int i; + + if (num - 1 > DP_REMOTE_I2C_READ_MAX_TRANSACTIONS) + return false; + + for (i = 0; i < num - 1; i++) { + if (msgs[i].flags & I2C_M_RD || + msgs[i].len > 0xff) + return false; + } + + return msgs[num - 1].flags & I2C_M_RD && + msgs[num - 1].len <= 0xff; +} + /* I2C device */ static int drm_dp_mst_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) @@ -3259,7 +3276,6 @@ static int drm_dp_mst_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs struct drm_dp_mst_branch *mstb; struct drm_dp_mst_topology_mgr *mgr = port->mgr; unsigned int i; - bool reading = false; struct drm_dp_sideband_msg_req_body msg; struct drm_dp_sideband_msg_tx *txmsg = NULL; int ret; @@ -3268,12 +3284,7 @@ static int drm_dp_mst_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs if (!mstb) return -EREMOTEIO; - /* construct i2c msg */ - /* see if last msg is a read */ - if (msgs[num - 1].flags & I2C_M_RD) - reading = true; - - if (!reading || (num - 1 > DP_REMOTE_I2C_READ_MAX_TRANSACTIONS)) { + if (!remote_i2c_read_ok(msgs, num)) { DRM_DEBUG_KMS("Unsupported I2C transaction for MST device\n"); ret = -EIO; goto out; From b962a12050a387e4bbf3a48745afe1d29d396b0d Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Mon, 22 Oct 2018 14:31:22 +0200 Subject: [PATCH 17/49] drm/atomic: integrate modeset lock with private objects Follow the same pattern of locking as with other state objects. This avoids boilerplate in the driver. Signed-off-by: Rob Clark Signed-off-by: Boris Brezillon Reviewed-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20181022123122.30468-1-boris.brezillon@bootlin.com --- drivers/gpu/drm/drm_atomic.c | 19 +++++++++--- drivers/gpu/drm/drm_dp_mst_topology.c | 2 +- drivers/gpu/drm/drm_mode_config.c | 1 + drivers/gpu/drm/drm_modeset_lock.c | 8 +++++ drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 2 +- drivers/gpu/drm/tegra/hub.c | 2 +- drivers/gpu/drm/vc4/vc4_kms.c | 3 +- include/drm/drm_atomic.h | 37 +++++++++++++++++++++++- include/drm/drm_mode_config.h | 9 ++++++ 9 files changed, 74 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 9ac26437051b..008224f376fe 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -676,6 +676,7 @@ static void drm_atomic_plane_print_state(struct drm_printer *p, /** * drm_atomic_private_obj_init - initialize private object + * @dev: DRM device this object will be attached to * @obj: private object * @state: initial private object state * @funcs: pointer to the struct of function pointers that identify the object @@ -685,14 +686,18 @@ static void drm_atomic_plane_print_state(struct drm_printer *p, * driver private object that needs its own atomic state. */ void -drm_atomic_private_obj_init(struct drm_private_obj *obj, +drm_atomic_private_obj_init(struct drm_device *dev, + struct drm_private_obj *obj, struct drm_private_state *state, const struct drm_private_state_funcs *funcs) { memset(obj, 0, sizeof(*obj)); + drm_modeset_lock_init(&obj->lock); + obj->state = state; obj->funcs = funcs; + list_add_tail(&obj->head, &dev->mode_config.privobj_list); } EXPORT_SYMBOL(drm_atomic_private_obj_init); @@ -705,7 +710,9 @@ EXPORT_SYMBOL(drm_atomic_private_obj_init); void drm_atomic_private_obj_fini(struct drm_private_obj *obj) { + list_del(&obj->head); obj->funcs->atomic_destroy_state(obj, obj->state); + drm_modeset_lock_fini(&obj->lock); } EXPORT_SYMBOL(drm_atomic_private_obj_fini); @@ -715,8 +722,8 @@ EXPORT_SYMBOL(drm_atomic_private_obj_fini); * @obj: private object to get the state for * * This function returns the private object state for the given private object, - * allocating the state if needed. It does not grab any locks as the caller is - * expected to care of any required locking. + * allocating the state if needed. It will also grab the relevant private + * object lock to make sure that the state is consistent. * * RETURNS: * @@ -726,7 +733,7 @@ struct drm_private_state * drm_atomic_get_private_obj_state(struct drm_atomic_state *state, struct drm_private_obj *obj) { - int index, num_objs, i; + int index, num_objs, i, ret; size_t size; struct __drm_private_objs_state *arr; struct drm_private_state *obj_state; @@ -735,6 +742,10 @@ drm_atomic_get_private_obj_state(struct drm_atomic_state *state, if (obj == state->private_objs[i].ptr) return state->private_objs[i].state; + ret = drm_modeset_lock(&obj->lock, state->acquire_ctx); + if (ret) + return ERR_PTR(ret); + num_objs = state->num_private_objs + 1; size = sizeof(*state->private_objs) * num_objs; arr = krealloc(state->private_objs, size, GFP_KERNEL); diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index f0cbd5fad8fc..5a73a0b1c9cd 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -3221,7 +3221,7 @@ int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr, /* max. time slots - one slot for MTP header */ mst_state->avail_slots = 63; - drm_atomic_private_obj_init(&mgr->base, + drm_atomic_private_obj_init(dev, &mgr->base, &mst_state->base, &mst_state_funcs); diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c index ee80788f2c40..931523c5bc9d 100644 --- a/drivers/gpu/drm/drm_mode_config.c +++ b/drivers/gpu/drm/drm_mode_config.c @@ -381,6 +381,7 @@ void drm_mode_config_init(struct drm_device *dev) INIT_LIST_HEAD(&dev->mode_config.property_list); INIT_LIST_HEAD(&dev->mode_config.property_blob_list); INIT_LIST_HEAD(&dev->mode_config.plane_list); + INIT_LIST_HEAD(&dev->mode_config.privobj_list); idr_init(&dev->mode_config.crtc_idr); idr_init(&dev->mode_config.tile_idr); ida_init(&dev->mode_config.connector_ida); diff --git a/drivers/gpu/drm/drm_modeset_lock.c b/drivers/gpu/drm/drm_modeset_lock.c index 51f534db9107..81dd11901ffd 100644 --- a/drivers/gpu/drm/drm_modeset_lock.c +++ b/drivers/gpu/drm/drm_modeset_lock.c @@ -22,6 +22,7 @@ */ #include +#include #include #include @@ -394,6 +395,7 @@ EXPORT_SYMBOL(drm_modeset_unlock); int drm_modeset_lock_all_ctx(struct drm_device *dev, struct drm_modeset_acquire_ctx *ctx) { + struct drm_private_obj *privobj; struct drm_crtc *crtc; struct drm_plane *plane; int ret; @@ -414,6 +416,12 @@ int drm_modeset_lock_all_ctx(struct drm_device *dev, return ret; } + drm_for_each_privobj(privobj, dev) { + ret = drm_modeset_lock(&privobj->lock, ctx); + if (ret) + return ret; + } + return 0; } EXPORT_SYMBOL(drm_modeset_lock_all_ctx); diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c index bddd625ab91b..f71d8cf2261b 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c @@ -144,7 +144,7 @@ static int mdp5_global_obj_init(struct mdp5_kms *mdp5_kms) state->mdp5_kms = mdp5_kms; - drm_atomic_private_obj_init(&mdp5_kms->glob_state, + drm_atomic_private_obj_init(mdp5_kms->dev, &mdp5_kms->glob_state, &state->base, &mdp5_global_state_funcs); return 0; diff --git a/drivers/gpu/drm/tegra/hub.c b/drivers/gpu/drm/tegra/hub.c index 6112d9042979..3e26be5359cf 100644 --- a/drivers/gpu/drm/tegra/hub.c +++ b/drivers/gpu/drm/tegra/hub.c @@ -716,7 +716,7 @@ static int tegra_display_hub_init(struct host1x_client *client) if (!state) return -ENOMEM; - drm_atomic_private_obj_init(&hub->base, &state->base, + drm_atomic_private_obj_init(drm, &hub->base, &state->base, &tegra_display_hub_state_funcs); tegra->hub = hub; diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index 1f94b9affe4b..0490edb192a1 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -432,7 +432,8 @@ int vc4_kms_load(struct drm_device *dev) ctm_state = kzalloc(sizeof(*ctm_state), GFP_KERNEL); if (!ctm_state) return -ENOMEM; - drm_atomic_private_obj_init(&vc4->ctm_manager, &ctm_state->base, + + drm_atomic_private_obj_init(dev, &vc4->ctm_manager, &ctm_state->base, &vc4_ctm_state_funcs); drm_mode_config_reset(dev); diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index f9b35834c45d..cac4a1b6b0e8 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -228,8 +228,30 @@ struct drm_private_state_funcs { * Currently only tracks the state update functions and the opaque driver * private state itself, but in the future might also track which * &drm_modeset_lock is required to duplicate and update this object's state. + * + * All private objects must be initialized before the DRM device they are + * attached to is registered to the DRM subsystem (call to drm_dev_register()) + * and should stay around until this DRM device is unregistered (call to + * drm_dev_unregister()). In other words, private objects lifetime is tied + * to the DRM device lifetime. This implies that: + * + * 1/ all calls to drm_atomic_private_obj_init() must be done before calling + * drm_dev_register() + * 2/ all calls to drm_atomic_private_obj_fini() must be done after calling + * drm_dev_unregister() */ struct drm_private_obj { + /** + * @head: List entry used to attach a private object to a &drm_device + * (queued to &drm_mode_config.privobj_list). + */ + struct list_head head; + + /** + * @lock: Modeset lock to protect the state object. + */ + struct drm_modeset_lock lock; + /** * @state: Current atomic state for this driver private object. */ @@ -244,6 +266,18 @@ struct drm_private_obj { const struct drm_private_state_funcs *funcs; }; +/** + * drm_for_each_privobj() - private object iterator + * + * @privobj: pointer to the current private object. Updated after each + * iteration + * @dev: the DRM device we want get private objects from + * + * Allows one to iterate over all private objects attached to @dev + */ +#define drm_for_each_privobj(privobj, dev) \ + list_for_each_entry(privobj, &(dev)->mode_config.privobj_list, head) + /** * struct drm_private_state - base struct for driver private object state * @state: backpointer to global drm_atomic_state @@ -400,7 +434,8 @@ struct drm_connector_state * __must_check drm_atomic_get_connector_state(struct drm_atomic_state *state, struct drm_connector *connector); -void drm_atomic_private_obj_init(struct drm_private_obj *obj, +void drm_atomic_private_obj_init(struct drm_device *dev, + struct drm_private_obj *obj, struct drm_private_state *state, const struct drm_private_state_funcs *funcs); void drm_atomic_private_obj_fini(struct drm_private_obj *obj); diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h index 5dbeabdbaf91..d1e27836e0cd 100644 --- a/include/drm/drm_mode_config.h +++ b/include/drm/drm_mode_config.h @@ -512,6 +512,15 @@ struct drm_mode_config { */ struct list_head property_list; + /** + * @privobj_list: + * + * List of private objects linked with &drm_private_obj.head. This is + * invariant over the lifetime of a device and hence doesn't need any + * locks. + */ + struct list_head privobj_list; + int min_width, min_height; int max_width, max_height; const struct drm_mode_config_funcs *funcs; From 3415701a5eae5c34d07e4b39ae7086eca66e94aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Fri, 7 Dec 2018 20:10:17 +0100 Subject: [PATCH 18/49] drm/etnaviv: fix for 64bit seqno change MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The fence seqno is now 64bit, fixes build warning. Signed-off-by: Christian König Acked-by: Lucas Stach Acked-by: Alex Deucher Link: https://patchwork.freedesktop.org/patch/267136/ --- drivers/gpu/drm/etnaviv/etnaviv_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c b/drivers/gpu/drm/etnaviv/etnaviv_gem.c index 1fa74226db91..5c48915f492d 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c @@ -449,7 +449,7 @@ static void etnaviv_gem_describe_fence(struct dma_fence *fence, const char *type, struct seq_file *m) { if (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) - seq_printf(m, "\t%9s: %s %s seq %u\n", + seq_printf(m, "\t%9s: %s %s seq %llu\n", type, fence->ops->get_driver_name(fence), fence->ops->get_timeline_name(fence), From 61a98b1b9a8c7a21a2d666a090dcf5f1c70c659f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Tue, 11 Dec 2018 18:34:41 +0800 Subject: [PATCH 19/49] drm/syncobj: remove drm_syncobj_cb and cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This completes "drm/syncobj: Drop add/remove_callback from driver interface" and cleans up the implementation a bit. Signed-off-by: Christian König Reviewed-by: Chunming Zhou Link: https://patchwork.freedesktop.org/patch/266255/ --- drivers/gpu/drm/drm_syncobj.c | 93 ++++++++++++----------------------- include/drm/drm_syncobj.h | 21 -------- 2 files changed, 31 insertions(+), 83 deletions(-) diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c index db30a0e89db8..e19525af0cce 100644 --- a/drivers/gpu/drm/drm_syncobj.c +++ b/drivers/gpu/drm/drm_syncobj.c @@ -56,6 +56,16 @@ #include "drm_internal.h" #include +struct syncobj_wait_entry { + struct list_head node; + struct task_struct *task; + struct dma_fence *fence; + struct dma_fence_cb fence_cb; +}; + +static void syncobj_wait_syncobj_func(struct drm_syncobj *syncobj, + struct syncobj_wait_entry *wait); + /** * drm_syncobj_find - lookup and reference a sync object. * @file_private: drm file private pointer @@ -82,58 +92,33 @@ struct drm_syncobj *drm_syncobj_find(struct drm_file *file_private, } EXPORT_SYMBOL(drm_syncobj_find); -static void drm_syncobj_add_callback_locked(struct drm_syncobj *syncobj, - struct drm_syncobj_cb *cb, - drm_syncobj_func_t func) +static void drm_syncobj_fence_add_wait(struct drm_syncobj *syncobj, + struct syncobj_wait_entry *wait) { - cb->func = func; - list_add_tail(&cb->node, &syncobj->cb_list); -} - -static int drm_syncobj_fence_get_or_add_callback(struct drm_syncobj *syncobj, - struct dma_fence **fence, - struct drm_syncobj_cb *cb, - drm_syncobj_func_t func) -{ - int ret; - - *fence = drm_syncobj_fence_get(syncobj); - if (*fence) - return 1; + if (wait->fence) + return; spin_lock(&syncobj->lock); /* We've already tried once to get a fence and failed. Now that we * have the lock, try one more time just to be sure we don't add a * callback when a fence has already been set. */ - if (syncobj->fence) { - *fence = dma_fence_get(rcu_dereference_protected(syncobj->fence, - lockdep_is_held(&syncobj->lock))); - ret = 1; - } else { - *fence = NULL; - drm_syncobj_add_callback_locked(syncobj, cb, func); - ret = 0; - } - spin_unlock(&syncobj->lock); - - return ret; -} - -void drm_syncobj_add_callback(struct drm_syncobj *syncobj, - struct drm_syncobj_cb *cb, - drm_syncobj_func_t func) -{ - spin_lock(&syncobj->lock); - drm_syncobj_add_callback_locked(syncobj, cb, func); + if (syncobj->fence) + wait->fence = dma_fence_get( + rcu_dereference_protected(syncobj->fence, 1)); + else + list_add_tail(&wait->node, &syncobj->cb_list); spin_unlock(&syncobj->lock); } -void drm_syncobj_remove_callback(struct drm_syncobj *syncobj, - struct drm_syncobj_cb *cb) +static void drm_syncobj_remove_wait(struct drm_syncobj *syncobj, + struct syncobj_wait_entry *wait) { + if (!wait->node.next) + return; + spin_lock(&syncobj->lock); - list_del_init(&cb->node); + list_del_init(&wait->node); spin_unlock(&syncobj->lock); } @@ -148,7 +133,7 @@ void drm_syncobj_replace_fence(struct drm_syncobj *syncobj, struct dma_fence *fence) { struct dma_fence *old_fence; - struct drm_syncobj_cb *cur, *tmp; + struct syncobj_wait_entry *cur, *tmp; if (fence) dma_fence_get(fence); @@ -162,7 +147,7 @@ void drm_syncobj_replace_fence(struct drm_syncobj *syncobj, if (fence != old_fence) { list_for_each_entry_safe(cur, tmp, &syncobj->cb_list, node) { list_del_init(&cur->node); - cur->func(syncobj, cur); + syncobj_wait_syncobj_func(syncobj, cur); } } @@ -608,13 +593,6 @@ drm_syncobj_fd_to_handle_ioctl(struct drm_device *dev, void *data, &args->handle); } -struct syncobj_wait_entry { - struct task_struct *task; - struct dma_fence *fence; - struct dma_fence_cb fence_cb; - struct drm_syncobj_cb syncobj_cb; -}; - static void syncobj_wait_fence_func(struct dma_fence *fence, struct dma_fence_cb *cb) { @@ -625,11 +603,8 @@ static void syncobj_wait_fence_func(struct dma_fence *fence, } static void syncobj_wait_syncobj_func(struct drm_syncobj *syncobj, - struct drm_syncobj_cb *cb) + struct syncobj_wait_entry *wait) { - struct syncobj_wait_entry *wait = - container_of(cb, struct syncobj_wait_entry, syncobj_cb); - /* This happens inside the syncobj lock */ wait->fence = dma_fence_get(rcu_dereference_protected(syncobj->fence, lockdep_is_held(&syncobj->lock))); @@ -688,12 +663,8 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs, */ if (flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT) { - for (i = 0; i < count; ++i) { - drm_syncobj_fence_get_or_add_callback(syncobjs[i], - &entries[i].fence, - &entries[i].syncobj_cb, - syncobj_wait_syncobj_func); - } + for (i = 0; i < count; ++i) + drm_syncobj_fence_add_wait(syncobjs[i], &entries[i]); } do { @@ -742,9 +713,7 @@ done_waiting: cleanup_entries: for (i = 0; i < count; ++i) { - if (entries[i].syncobj_cb.func) - drm_syncobj_remove_callback(syncobjs[i], - &entries[i].syncobj_cb); + drm_syncobj_remove_wait(syncobjs[i], &entries[i]); if (entries[i].fence_cb.func) dma_fence_remove_callback(entries[i].fence, &entries[i].fence_cb); diff --git a/include/drm/drm_syncobj.h b/include/drm/drm_syncobj.h index b1fe921f8e8f..7c6ed845c70d 100644 --- a/include/drm/drm_syncobj.h +++ b/include/drm/drm_syncobj.h @@ -28,8 +28,6 @@ #include "linux/dma-fence.h" -struct drm_syncobj_cb; - /** * struct drm_syncobj - sync object. * @@ -62,25 +60,6 @@ struct drm_syncobj { struct file *file; }; -typedef void (*drm_syncobj_func_t)(struct drm_syncobj *syncobj, - struct drm_syncobj_cb *cb); - -/** - * struct drm_syncobj_cb - callback for drm_syncobj_add_callback - * @node: used by drm_syncob_add_callback to append this struct to - * &drm_syncobj.cb_list - * @func: drm_syncobj_func_t to call - * - * This struct will be initialized by drm_syncobj_add_callback, additional - * data can be passed along by embedding drm_syncobj_cb in another struct. - * The callback will get called the next time drm_syncobj_replace_fence is - * called. - */ -struct drm_syncobj_cb { - struct list_head node; - drm_syncobj_func_t func; -}; - void drm_syncobj_free(struct kref *kref); /** From 7ce5362815bb55a200b93ca3f267eda90fc28130 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 10 Dec 2018 11:03:57 +0100 Subject: [PATCH 20/49] drm/qxl: Don't set the dpms hook Doesn't do anything with atomic. Signed-off-by: Daniel Vetter Cc: Dave Airlie Cc: Gerd Hoffmann Cc: virtualization@lists.linux-foundation.org Cc: spice-devel@lists.freedesktop.org Reviewed-by: Gerd Hoffmann Reviewed-by: Alex Deucher Link: https://patchwork.freedesktop.org/patch/msgid/20181210100359.22507-6-daniel.vetter@ffwll.ch --- drivers/gpu/drm/qxl/qxl_display.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c index ce0b9c40fc21..72a1784dae54 100644 --- a/drivers/gpu/drm/qxl/qxl_display.c +++ b/drivers/gpu/drm/qxl/qxl_display.c @@ -1010,7 +1010,6 @@ static void qxl_conn_destroy(struct drm_connector *connector) } static const struct drm_connector_funcs qxl_connector_funcs = { - .dpms = drm_helper_connector_dpms, .detect = qxl_conn_detect, .fill_modes = drm_helper_probe_single_connector_modes, .destroy = qxl_conn_destroy, From cad5290a2f79c7eaeda11bba02dd1cb6d096359a Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 10 Dec 2018 11:03:58 +0100 Subject: [PATCH 21/49] drm/xen: Don't set the dpms hook Doesn't do anything for atomic. Signed-off-by: Daniel Vetter Cc: Oleksandr Andrushchenko Cc: xen-devel@lists.xen.org Reviewed-by: Alex Deucher Reviewed-by: Oleksandr Andrushchenko Link: https://patchwork.freedesktop.org/patch/msgid/20181210100359.22507-7-daniel.vetter@ffwll.ch --- drivers/gpu/drm/xen/xen_drm_front_conn.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/xen/xen_drm_front_conn.c b/drivers/gpu/drm/xen/xen_drm_front_conn.c index c91ae532fa55..54af2669b1b3 100644 --- a/drivers/gpu/drm/xen/xen_drm_front_conn.c +++ b/drivers/gpu/drm/xen/xen_drm_front_conn.c @@ -89,7 +89,6 @@ static const struct drm_connector_helper_funcs connector_helper_funcs = { }; static const struct drm_connector_funcs connector_funcs = { - .dpms = drm_helper_connector_dpms, .fill_modes = drm_helper_probe_single_connector_modes, .destroy = drm_connector_cleanup, .reset = drm_atomic_helper_connector_reset, From 63d5e06aa38182da47bccde16fac058b0b2d53c7 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Fri, 30 Nov 2018 11:24:49 +0100 Subject: [PATCH 22/49] drm/rockchip: Add implicit fencing support for planes Render like lima will attach a fence to the framebuffer dma_buf, so the display driver should wait for it to finish before showing the framebufferto prevent tearing. Generally tested on rk3188, rk3288, rk3328 and rk3399 and together with an actual lima-based kmscube on rk3188 and rk3328. Suggested-by: Qiang Yu Signed-off-by: Heiko Stuebner Reviewed-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20181130102449.6430-1-heiko@sntech.de --- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index fb70fb486fbf..db8358e6d230 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #ifdef CONFIG_DRM_ANALOGIX_DP #include @@ -823,6 +824,7 @@ static const struct drm_plane_helper_funcs plane_helper_funcs = { .atomic_check = vop_plane_atomic_check, .atomic_update = vop_plane_atomic_update, .atomic_disable = vop_plane_atomic_disable, + .prepare_fb = drm_gem_fb_prepare_fb, }; static const struct drm_plane_funcs vop_plane_funcs = { From b5f06893c4992553a12c66ca094a09fb245d280e Mon Sep 17 00:00:00 2001 From: Shayenne da Luz Moura Date: Thu, 13 Dec 2018 19:29:57 -0200 Subject: [PATCH 23/49] drm: Rename crtc_idr as object_idr to KMS cleanups This patch solves this TODO task: drm_mode_config.crtc_idr is misnamed, since it contains all KMS object. Should be renamed to drm_mode_config.object_idr. Signed-off-by: Shayenne da Luz Moura [danvet: resolve conflict with addition of privobj_list.] Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20181213212957.vkitkyl5cj2qh7qr@smtp.gmail.com --- drivers/gpu/drm/drm_lease.c | 6 +++--- drivers/gpu/drm/drm_mode_config.c | 4 ++-- drivers/gpu/drm/drm_mode_object.c | 8 ++++---- include/drm/drm_mode_config.h | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/drm_lease.c b/drivers/gpu/drm/drm_lease.c index 3650d3c46718..d9b4d3ff06f6 100644 --- a/drivers/gpu/drm/drm_lease.c +++ b/drivers/gpu/drm/drm_lease.c @@ -218,7 +218,7 @@ static struct drm_master *drm_lease_create(struct drm_master *lessor, struct idr idr_for_each_entry(leases, entry, object) { error = 0; - if (!idr_find(&dev->mode_config.crtc_idr, object)) + if (!idr_find(&dev->mode_config.object_idr, object)) error = -ENOENT; else if (!_drm_lease_held_master(lessor, object)) error = -EACCES; @@ -439,7 +439,7 @@ static int fill_object_idr(struct drm_device *dev, /* * We're using an IDR to hold the set of leased * objects, but we don't need to point at the object's - * data structure from the lease as the main crtc_idr + * data structure from the lease as the main object_idr * will be used to actually find that. Instead, all we * really want is a 'leased/not-leased' result, for * which any non-NULL pointer will work fine. @@ -687,7 +687,7 @@ int drm_mode_get_lease_ioctl(struct drm_device *dev, if (lessee->lessor == NULL) /* owner can use all objects */ - object_idr = &lessee->dev->mode_config.crtc_idr; + object_idr = &lessee->dev->mode_config.object_idr; else /* lessee can only use allowed object */ object_idr = &lessee->leases; diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c index 931523c5bc9d..037e243ec863 100644 --- a/drivers/gpu/drm/drm_mode_config.c +++ b/drivers/gpu/drm/drm_mode_config.c @@ -382,7 +382,7 @@ void drm_mode_config_init(struct drm_device *dev) INIT_LIST_HEAD(&dev->mode_config.property_blob_list); INIT_LIST_HEAD(&dev->mode_config.plane_list); INIT_LIST_HEAD(&dev->mode_config.privobj_list); - idr_init(&dev->mode_config.crtc_idr); + idr_init(&dev->mode_config.object_idr); idr_init(&dev->mode_config.tile_idr); ida_init(&dev->mode_config.connector_ida); spin_lock_init(&dev->mode_config.connector_list_lock); @@ -485,7 +485,7 @@ void drm_mode_config_cleanup(struct drm_device *dev) ida_destroy(&dev->mode_config.connector_ida); idr_destroy(&dev->mode_config.tile_idr); - idr_destroy(&dev->mode_config.crtc_idr); + idr_destroy(&dev->mode_config.object_idr); drm_modeset_lock_fini(&dev->mode_config.connection_mutex); } EXPORT_SYMBOL(drm_mode_config_cleanup); diff --git a/drivers/gpu/drm/drm_mode_object.c b/drivers/gpu/drm/drm_mode_object.c index cd9bc0ce9be0..bb1dd46496cd 100644 --- a/drivers/gpu/drm/drm_mode_object.c +++ b/drivers/gpu/drm/drm_mode_object.c @@ -38,7 +38,7 @@ int __drm_mode_object_add(struct drm_device *dev, struct drm_mode_object *obj, int ret; mutex_lock(&dev->mode_config.idr_mutex); - ret = idr_alloc(&dev->mode_config.crtc_idr, register_obj ? obj : NULL, + ret = idr_alloc(&dev->mode_config.object_idr, register_obj ? obj : NULL, 1, 0, GFP_KERNEL); if (ret >= 0) { /* @@ -79,7 +79,7 @@ void drm_mode_object_register(struct drm_device *dev, struct drm_mode_object *obj) { mutex_lock(&dev->mode_config.idr_mutex); - idr_replace(&dev->mode_config.crtc_idr, obj, obj->id); + idr_replace(&dev->mode_config.object_idr, obj, obj->id); mutex_unlock(&dev->mode_config.idr_mutex); } @@ -99,7 +99,7 @@ void drm_mode_object_unregister(struct drm_device *dev, { mutex_lock(&dev->mode_config.idr_mutex); if (object->id) { - idr_remove(&dev->mode_config.crtc_idr, object->id); + idr_remove(&dev->mode_config.object_idr, object->id); object->id = 0; } mutex_unlock(&dev->mode_config.idr_mutex); @@ -131,7 +131,7 @@ struct drm_mode_object *__drm_mode_object_find(struct drm_device *dev, struct drm_mode_object *obj = NULL; mutex_lock(&dev->mode_config.idr_mutex); - obj = idr_find(&dev->mode_config.crtc_idr, id); + obj = idr_find(&dev->mode_config.object_idr, id); if (obj && type != DRM_MODE_OBJECT_ANY && obj->type != type) obj = NULL; if (obj && obj->id != id) diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h index d1e27836e0cd..88c536bd9a7b 100644 --- a/include/drm/drm_mode_config.h +++ b/include/drm/drm_mode_config.h @@ -391,18 +391,18 @@ struct drm_mode_config { /** * @idr_mutex: * - * Mutex for KMS ID allocation and management. Protects both @crtc_idr + * Mutex for KMS ID allocation and management. Protects both @object_idr * and @tile_idr. */ struct mutex idr_mutex; /** - * @crtc_idr: + * @object_idr: * * Main KMS ID tracking object. Use this idr for all IDs, fb, crtc, * connector, modes - just makes life easier to have only one. */ - struct idr crtc_idr; + struct idr object_idr; /** * @tile_idr: From f536e00c46d22ccd1b2aada5b22754c35d9487ce Mon Sep 17 00:00:00 2001 From: Lyude Paul Date: Tue, 11 Dec 2018 18:50:26 -0500 Subject: [PATCH 24/49] drm/dp_mst: Fix memory leak in drm_dp_mst_topology_mgr_destroy() We need to call drm_dp_mst_topology_mgr_set_mst(mgr, false) when destroying the topology manager in order to ensure that the root mstb and all of it's descendents are actually destroyed, and additionally to try to make sure that we leave the hub in a clean state. Signed-off-by: Lyude Paul Reviewed-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20181211235026.21758-1-lyude@redhat.com --- drivers/gpu/drm/drm_dp_mst_topology.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 5a73a0b1c9cd..ad0fb6d003be 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -3235,6 +3235,7 @@ EXPORT_SYMBOL(drm_dp_mst_topology_mgr_init); */ void drm_dp_mst_topology_mgr_destroy(struct drm_dp_mst_topology_mgr *mgr) { + drm_dp_mst_topology_mgr_set_mst(mgr, false); flush_work(&mgr->work); flush_work(&mgr->destroy_connector_work); mutex_lock(&mgr->payload_lock); From 18ce0906d96234d7932afc90ed7ce4a338de989e Mon Sep 17 00:00:00 2001 From: Shayenne da Luz Moura Date: Thu, 13 Dec 2018 20:55:37 -0200 Subject: [PATCH 25/49] drm: Remove complete task from TODO documentation This patch remove the follow complete task from TODO documentation: drm_mode_config.crtc_idr is misnamed, since it contains all KMS object. Should be renamed to drm_mode_config.object_idr. Signed-off-by: Shayenne da Luz Moura Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20181213225537.nq4dwidn6tma33iv@smtp.gmail.com --- Documentation/gpu/todo.rst | 3 --- 1 file changed, 3 deletions(-) diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst index 14191b64446d..41da7b06195c 100644 --- a/Documentation/gpu/todo.rst +++ b/Documentation/gpu/todo.rst @@ -354,9 +354,6 @@ KMS cleanups Some of these date from the very introduction of KMS in 2008 ... -- drm_mode_config.crtc_idr is misnamed, since it contains all KMS object. Should - be renamed to drm_mode_config.object_idr. - - drm_display_mode doesn't need to be derived from drm_mode_object. That's leftovers from older (never merged into upstream) KMS designs where modes where set using their ID, including support to add/remove modes. From 48a77d66cb7f557635f4fccd5abfc1ac2f71b9de Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 13 Dec 2018 14:49:15 +0100 Subject: [PATCH 26/49] drm/virtio: switch to generic fbdev emulation Signed-off-by: Gerd Hoffmann Reviewed-by: Dave Airlie Link: http://patchwork.freedesktop.org/patch/msgid/20181213134915.24722-1-kraxel@redhat.com --- drivers/gpu/drm/virtio/virtgpu_display.c | 1 - drivers/gpu/drm/virtio/virtgpu_drv.c | 9 +- drivers/gpu/drm/virtio/virtgpu_drv.h | 14 -- drivers/gpu/drm/virtio/virtgpu_fb.c | 191 ----------------------- drivers/gpu/drm/virtio/virtgpu_kms.c | 8 - 5 files changed, 8 insertions(+), 215 deletions(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c index b5580b11a063..e1c223e18d86 100644 --- a/drivers/gpu/drm/virtio/virtgpu_display.c +++ b/drivers/gpu/drm/virtio/virtgpu_display.c @@ -390,6 +390,5 @@ void virtio_gpu_modeset_fini(struct virtio_gpu_device *vgdev) for (i = 0 ; i < vgdev->num_scanouts; ++i) kfree(vgdev->outputs[i].edid); - virtio_gpu_fbdev_fini(vgdev); drm_mode_config_cleanup(vgdev->ddev); } diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.c b/drivers/gpu/drm/virtio/virtgpu_drv.c index f7f32a885af7..7df50920c1e0 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.c +++ b/drivers/gpu/drm/virtio/virtgpu_drv.c @@ -42,13 +42,20 @@ module_param_named(modeset, virtio_gpu_modeset, int, 0400); static int virtio_gpu_probe(struct virtio_device *vdev) { + int ret; + if (vgacon_text_force() && virtio_gpu_modeset == -1) return -EINVAL; if (virtio_gpu_modeset == 0) return -EINVAL; - return drm_virtio_init(&driver, vdev); + ret = drm_virtio_init(&driver, vdev); + if (ret) + return ret; + + drm_fbdev_generic_setup(vdev->priv, 32); + return 0; } static void virtio_gpu_remove(struct virtio_device *vdev) diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h index 1deb41d42ea4..63704915f8ce 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.h +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h @@ -137,19 +137,10 @@ struct virtio_gpu_framebuffer { #define to_virtio_gpu_framebuffer(x) \ container_of(x, struct virtio_gpu_framebuffer, base) -struct virtio_gpu_fbdev { - struct drm_fb_helper helper; - struct virtio_gpu_framebuffer vgfb; - struct virtio_gpu_device *vgdev; - struct delayed_work work; -}; - struct virtio_gpu_mman { struct ttm_bo_device bdev; }; -struct virtio_gpu_fbdev; - struct virtio_gpu_queue { struct virtqueue *vq; spinlock_t qlock; @@ -180,8 +171,6 @@ struct virtio_gpu_device { struct virtio_gpu_mman mman; - /* pointer to fbdev info structure */ - struct virtio_gpu_fbdev *vgfbdev; struct virtio_gpu_output outputs[VIRTIO_GPU_MAX_SCANOUTS]; uint32_t num_scanouts; @@ -249,9 +238,6 @@ int virtio_gpu_mode_dumb_mmap(struct drm_file *file_priv, uint32_t handle, uint64_t *offset_p); /* virtio_fb */ -#define VIRTIO_GPUFB_CONN_LIMIT 1 -int virtio_gpu_fbdev_init(struct virtio_gpu_device *vgdev); -void virtio_gpu_fbdev_fini(struct virtio_gpu_device *vgdev); int virtio_gpu_surface_dirty(struct virtio_gpu_framebuffer *qfb, struct drm_clip_rect *clips, unsigned int num_clips); diff --git a/drivers/gpu/drm/virtio/virtgpu_fb.c b/drivers/gpu/drm/virtio/virtgpu_fb.c index fb1cc8b2f119..b07584b1c2bf 100644 --- a/drivers/gpu/drm/virtio/virtgpu_fb.c +++ b/drivers/gpu/drm/virtio/virtgpu_fb.c @@ -27,8 +27,6 @@ #include #include "virtgpu_drv.h" -#define VIRTIO_GPU_FBCON_POLL_PERIOD (HZ / 60) - static int virtio_gpu_dirty_update(struct virtio_gpu_framebuffer *fb, bool store, int x, int y, int width, int height) @@ -150,192 +148,3 @@ int virtio_gpu_surface_dirty(struct virtio_gpu_framebuffer *vgfb, left, top, right - left, bottom - top); return 0; } - -static void virtio_gpu_fb_dirty_work(struct work_struct *work) -{ - struct delayed_work *delayed_work = to_delayed_work(work); - struct virtio_gpu_fbdev *vfbdev = - container_of(delayed_work, struct virtio_gpu_fbdev, work); - struct virtio_gpu_framebuffer *vgfb = &vfbdev->vgfb; - - virtio_gpu_dirty_update(&vfbdev->vgfb, false, vgfb->x1, vgfb->y1, - vgfb->x2 - vgfb->x1, vgfb->y2 - vgfb->y1); -} - -static void virtio_gpu_3d_fillrect(struct fb_info *info, - const struct fb_fillrect *rect) -{ - struct virtio_gpu_fbdev *vfbdev = info->par; - - drm_fb_helper_sys_fillrect(info, rect); - virtio_gpu_dirty_update(&vfbdev->vgfb, true, rect->dx, rect->dy, - rect->width, rect->height); - schedule_delayed_work(&vfbdev->work, VIRTIO_GPU_FBCON_POLL_PERIOD); -} - -static void virtio_gpu_3d_copyarea(struct fb_info *info, - const struct fb_copyarea *area) -{ - struct virtio_gpu_fbdev *vfbdev = info->par; - - drm_fb_helper_sys_copyarea(info, area); - virtio_gpu_dirty_update(&vfbdev->vgfb, true, area->dx, area->dy, - area->width, area->height); - schedule_delayed_work(&vfbdev->work, VIRTIO_GPU_FBCON_POLL_PERIOD); -} - -static void virtio_gpu_3d_imageblit(struct fb_info *info, - const struct fb_image *image) -{ - struct virtio_gpu_fbdev *vfbdev = info->par; - - drm_fb_helper_sys_imageblit(info, image); - virtio_gpu_dirty_update(&vfbdev->vgfb, true, image->dx, image->dy, - image->width, image->height); - schedule_delayed_work(&vfbdev->work, VIRTIO_GPU_FBCON_POLL_PERIOD); -} - -static struct fb_ops virtio_gpufb_ops = { - .owner = THIS_MODULE, - DRM_FB_HELPER_DEFAULT_OPS, - .fb_fillrect = virtio_gpu_3d_fillrect, - .fb_copyarea = virtio_gpu_3d_copyarea, - .fb_imageblit = virtio_gpu_3d_imageblit, -}; - -static int virtio_gpufb_create(struct drm_fb_helper *helper, - struct drm_fb_helper_surface_size *sizes) -{ - struct virtio_gpu_fbdev *vfbdev = - container_of(helper, struct virtio_gpu_fbdev, helper); - struct drm_device *dev = helper->dev; - struct virtio_gpu_device *vgdev = dev->dev_private; - struct fb_info *info; - struct drm_framebuffer *fb; - struct drm_mode_fb_cmd2 mode_cmd = {}; - struct virtio_gpu_object *obj; - uint32_t format, size; - int ret; - - mode_cmd.width = sizes->surface_width; - mode_cmd.height = sizes->surface_height; - mode_cmd.pitches[0] = mode_cmd.width * 4; - mode_cmd.pixel_format = DRM_FORMAT_HOST_XRGB8888; - - format = virtio_gpu_translate_format(mode_cmd.pixel_format); - if (format == 0) - return -EINVAL; - - size = mode_cmd.pitches[0] * mode_cmd.height; - obj = virtio_gpu_alloc_object(dev, size, false, true); - if (IS_ERR(obj)) - return PTR_ERR(obj); - - virtio_gpu_cmd_create_resource(vgdev, obj, format, - mode_cmd.width, mode_cmd.height); - - ret = virtio_gpu_object_kmap(obj); - if (ret) { - DRM_ERROR("failed to kmap fb %d\n", ret); - goto err_obj_vmap; - } - - /* attach the object to the resource */ - ret = virtio_gpu_object_attach(vgdev, obj, NULL); - if (ret) - goto err_obj_attach; - - info = drm_fb_helper_alloc_fbi(helper); - if (IS_ERR(info)) { - ret = PTR_ERR(info); - goto err_fb_alloc; - } - - info->par = helper; - - ret = virtio_gpu_framebuffer_init(dev, &vfbdev->vgfb, - &mode_cmd, &obj->gem_base); - if (ret) - goto err_fb_alloc; - - fb = &vfbdev->vgfb.base; - - vfbdev->helper.fb = fb; - - strcpy(info->fix.id, "virtiodrmfb"); - info->fbops = &virtio_gpufb_ops; - info->pixmap.flags = FB_PIXMAP_SYSTEM; - - info->screen_buffer = obj->vmap; - info->screen_size = obj->gem_base.size; - drm_fb_helper_fill_fix(info, fb->pitches[0], fb->format->depth); - drm_fb_helper_fill_var(info, &vfbdev->helper, - sizes->fb_width, sizes->fb_height); - - info->fix.mmio_start = 0; - info->fix.mmio_len = 0; - return 0; - -err_fb_alloc: - virtio_gpu_object_detach(vgdev, obj); -err_obj_attach: -err_obj_vmap: - virtio_gpu_gem_free_object(&obj->gem_base); - return ret; -} - -static int virtio_gpu_fbdev_destroy(struct drm_device *dev, - struct virtio_gpu_fbdev *vgfbdev) -{ - struct virtio_gpu_framebuffer *vgfb = &vgfbdev->vgfb; - - drm_fb_helper_unregister_fbi(&vgfbdev->helper); - - if (vgfb->base.obj[0]) - vgfb->base.obj[0] = NULL; - drm_fb_helper_fini(&vgfbdev->helper); - drm_framebuffer_cleanup(&vgfb->base); - - return 0; -} -static const struct drm_fb_helper_funcs virtio_gpu_fb_helper_funcs = { - .fb_probe = virtio_gpufb_create, -}; - -int virtio_gpu_fbdev_init(struct virtio_gpu_device *vgdev) -{ - struct virtio_gpu_fbdev *vgfbdev; - int bpp_sel = 32; /* TODO: parameter from somewhere? */ - int ret; - - vgfbdev = kzalloc(sizeof(struct virtio_gpu_fbdev), GFP_KERNEL); - if (!vgfbdev) - return -ENOMEM; - - vgfbdev->vgdev = vgdev; - vgdev->vgfbdev = vgfbdev; - INIT_DELAYED_WORK(&vgfbdev->work, virtio_gpu_fb_dirty_work); - - drm_fb_helper_prepare(vgdev->ddev, &vgfbdev->helper, - &virtio_gpu_fb_helper_funcs); - ret = drm_fb_helper_init(vgdev->ddev, &vgfbdev->helper, - VIRTIO_GPUFB_CONN_LIMIT); - if (ret) { - kfree(vgfbdev); - return ret; - } - - drm_fb_helper_single_add_all_connectors(&vgfbdev->helper); - drm_fb_helper_initial_config(&vgfbdev->helper, bpp_sel); - return 0; -} - -void virtio_gpu_fbdev_fini(struct virtio_gpu_device *vgdev) -{ - if (!vgdev->vgfbdev) - return; - - virtio_gpu_fbdev_destroy(vgdev->ddev, vgdev->vgfbdev); - kfree(vgdev->vgfbdev); - vgdev->vgfbdev = NULL; -} diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c b/drivers/gpu/drm/virtio/virtgpu_kms.c index 3af6181c05a8..1072064a0db2 100644 --- a/drivers/gpu/drm/virtio/virtgpu_kms.c +++ b/drivers/gpu/drm/virtio/virtgpu_kms.c @@ -28,11 +28,6 @@ #include #include "virtgpu_drv.h" -static int virtio_gpu_fbdev = 1; - -MODULE_PARM_DESC(fbdev, "Disable/Enable framebuffer device & console"); -module_param_named(fbdev, virtio_gpu_fbdev, int, 0400); - static void virtio_gpu_config_changed_work_func(struct work_struct *work) { struct virtio_gpu_device *vgdev = @@ -212,9 +207,6 @@ int virtio_gpu_driver_load(struct drm_device *dev, unsigned long flags) virtio_gpu_cmd_get_display_info(vgdev); wait_event_timeout(vgdev->resp_wq, !vgdev->display_info_pending, 5 * HZ); - if (virtio_gpu_fbdev) - virtio_gpu_fbdev_init(vgdev); - return 0; err_modeset: From fc63668656bdcad7317fbac0ca2b31ae9e81cf74 Mon Sep 17 00:00:00 2001 From: Lyude Paul Date: Thu, 13 Dec 2018 20:25:30 -0500 Subject: [PATCH 27/49] drm/dp_mst: Remove bogus conditional in drm_dp_update_payload_part1() There's no reason we need this, it's just confusing looking. Signed-off-by: Lyude Paul Cc: Juston Li Reviewed-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20181214012604.13746-2-lyude@redhat.com --- drivers/gpu/drm/drm_dp_mst_topology.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index ad0fb6d003be..9b1b5c9b1fa0 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -1896,9 +1896,7 @@ int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr) req_payload.num_slots = 0; } - if (mgr->payloads[i].start_slot != req_payload.start_slot) { - mgr->payloads[i].start_slot = req_payload.start_slot; - } + mgr->payloads[i].start_slot = req_payload.start_slot; /* work out what is required to happen with this payload */ if (mgr->payloads[i].num_slots != req_payload.num_slots) { From 706246c761ddd394e2b02f6dba2357d8eb5a7b5d Mon Sep 17 00:00:00 2001 From: Lyude Paul Date: Thu, 13 Dec 2018 20:25:31 -0500 Subject: [PATCH 28/49] drm/dp_mst: Refactor drm_dp_update_payload_part1() This: - Adds local variables in the first loop, instead of using array indices everywhere - Adds an early continue to reduce the indent level in the second loop There should be no functional changes here Signed-off-by: Lyude Paul Reviewed-by: Daniel Vetter Cc: Juston Li Link: https://patchwork.freedesktop.org/patch/msgid/20181214012604.13746-3-lyude@redhat.com --- drivers/gpu/drm/drm_dp_mst_topology.c | 71 ++++++++++++++++----------- 1 file changed, 42 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 9b1b5c9b1fa0..2ab16c9e6243 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -1879,39 +1879,48 @@ int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr) mutex_lock(&mgr->payload_lock); for (i = 0; i < mgr->max_payloads; i++) { + struct drm_dp_vcpi *vcpi = mgr->proposed_vcpis[i]; + struct drm_dp_payload *payload = &mgr->payloads[i]; + /* solve the current payloads - compare to the hw ones - update the hw view */ req_payload.start_slot = cur_slots; - if (mgr->proposed_vcpis[i]) { - port = container_of(mgr->proposed_vcpis[i], struct drm_dp_mst_port, vcpi); + if (vcpi) { + port = container_of(vcpi, struct drm_dp_mst_port, + vcpi); port = drm_dp_get_validated_port_ref(mgr, port); if (!port) { mutex_unlock(&mgr->payload_lock); return -EINVAL; } - req_payload.num_slots = mgr->proposed_vcpis[i]->num_slots; - req_payload.vcpi = mgr->proposed_vcpis[i]->vcpi; + req_payload.num_slots = vcpi->num_slots; + req_payload.vcpi = vcpi->vcpi; } else { port = NULL; req_payload.num_slots = 0; } - mgr->payloads[i].start_slot = req_payload.start_slot; + payload->start_slot = req_payload.start_slot; /* work out what is required to happen with this payload */ - if (mgr->payloads[i].num_slots != req_payload.num_slots) { + if (payload->num_slots != req_payload.num_slots) { /* need to push an update for this payload */ if (req_payload.num_slots) { - drm_dp_create_payload_step1(mgr, mgr->proposed_vcpis[i]->vcpi, &req_payload); - mgr->payloads[i].num_slots = req_payload.num_slots; - mgr->payloads[i].vcpi = req_payload.vcpi; - } else if (mgr->payloads[i].num_slots) { - mgr->payloads[i].num_slots = 0; - drm_dp_destroy_payload_step1(mgr, port, mgr->payloads[i].vcpi, &mgr->payloads[i]); - req_payload.payload_state = mgr->payloads[i].payload_state; - mgr->payloads[i].start_slot = 0; + drm_dp_create_payload_step1(mgr, vcpi->vcpi, + &req_payload); + payload->num_slots = req_payload.num_slots; + payload->vcpi = req_payload.vcpi; + + } else if (payload->num_slots) { + payload->num_slots = 0; + drm_dp_destroy_payload_step1(mgr, port, + payload->vcpi, + payload); + req_payload.payload_state = + payload->payload_state; + payload->start_slot = 0; } - mgr->payloads[i].payload_state = req_payload.payload_state; + payload->payload_state = req_payload.payload_state; } cur_slots += req_payload.num_slots; @@ -1920,22 +1929,26 @@ int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr) } for (i = 0; i < mgr->max_payloads; i++) { - if (mgr->payloads[i].payload_state == DP_PAYLOAD_DELETE_LOCAL) { - DRM_DEBUG_KMS("removing payload %d\n", i); - for (j = i; j < mgr->max_payloads - 1; j++) { - memcpy(&mgr->payloads[j], &mgr->payloads[j + 1], sizeof(struct drm_dp_payload)); - mgr->proposed_vcpis[j] = mgr->proposed_vcpis[j + 1]; - if (mgr->proposed_vcpis[j] && mgr->proposed_vcpis[j]->num_slots) { - set_bit(j + 1, &mgr->payload_mask); - } else { - clear_bit(j + 1, &mgr->payload_mask); - } - } - memset(&mgr->payloads[mgr->max_payloads - 1], 0, sizeof(struct drm_dp_payload)); - mgr->proposed_vcpis[mgr->max_payloads - 1] = NULL; - clear_bit(mgr->max_payloads, &mgr->payload_mask); + if (mgr->payloads[i].payload_state != DP_PAYLOAD_DELETE_LOCAL) + continue; + DRM_DEBUG_KMS("removing payload %d\n", i); + for (j = i; j < mgr->max_payloads - 1; j++) { + mgr->payloads[j] = mgr->payloads[j + 1]; + mgr->proposed_vcpis[j] = mgr->proposed_vcpis[j + 1]; + + if (mgr->proposed_vcpis[j] && + mgr->proposed_vcpis[j]->num_slots) { + set_bit(j + 1, &mgr->payload_mask); + } else { + clear_bit(j + 1, &mgr->payload_mask); + } } + + memset(&mgr->payloads[mgr->max_payloads - 1], 0, + sizeof(struct drm_dp_payload)); + mgr->proposed_vcpis[mgr->max_payloads - 1] = NULL; + clear_bit(mgr->max_payloads, &mgr->payload_mask); } mutex_unlock(&mgr->payload_lock); From 705c8160ce88825d2491aa55fa9da4fa79204c10 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 17 Dec 2018 10:00:38 +0300 Subject: [PATCH 29/49] drm: Fix an error pointer dereference() The drm_mode_create_tile_group() is only called from drm_parse_tiled_block() and the caller expects it to return a NULL on error. In other words, this function should match drm_mode_get_tile_group(). Signed-off-by: Dan Carpenter Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20181217065733.GA12159@kadam --- drivers/gpu/drm/drm_connector.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index fa9baacc863b..f0dd3315b1b8 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -1960,7 +1960,7 @@ EXPORT_SYMBOL(drm_mode_get_tile_group); * identifier for the tile group. * * RETURNS: - * new tile group or error. + * new tile group or NULL. */ struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev, char topology[8]) @@ -1970,7 +1970,7 @@ struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev, tg = kzalloc(sizeof(*tg), GFP_KERNEL); if (!tg) - return ERR_PTR(-ENOMEM); + return NULL; kref_init(&tg->refcount); memcpy(tg->group_data, topology, 8); @@ -1982,7 +1982,7 @@ struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev, tg->id = ret; } else { kfree(tg); - tg = ERR_PTR(ret); + tg = NULL; } mutex_unlock(&dev->mode_config.idr_mutex); From c27889ca3bb8bdc936bd0477125f0f6ff4c42df3 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 17 Dec 2018 10:03:44 +0300 Subject: [PATCH 30/49] drm/ati_pcigart: Fix error code in drm_ati_pcigart_init() The drm_ati_pcigart_init() function was originally suppose to return one on success and zero on failure, but these days it returns a mix of zero, one and -ENOMEM on failure. This patch cleans it up and modifies the caller so now the function returns zero on success and negative error codes on failure. Signed-off-by: Dan Carpenter Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20181217070344.GC12159@kadam --- drivers/gpu/drm/ati_pcigart.c | 7 ++++--- drivers/gpu/drm/r128/r128_cce.c | 5 +++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/ati_pcigart.c b/drivers/gpu/drm/ati_pcigart.c index 6c4d4b6eba80..2362f07fe1fc 100644 --- a/drivers/gpu/drm/ati_pcigart.c +++ b/drivers/gpu/drm/ati_pcigart.c @@ -103,7 +103,7 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga unsigned long pages; u32 *pci_gart = NULL, page_base, gart_idx; dma_addr_t bus_address = 0; - int i, j, ret = 0; + int i, j, ret = -ENOMEM; int max_ati_pages, max_real_pages; if (!entry) { @@ -117,7 +117,7 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga if (pci_set_dma_mask(dev->pdev, gart_info->table_mask)) { DRM_ERROR("fail to set dma mask to 0x%Lx\n", (unsigned long long)gart_info->table_mask); - ret = 1; + ret = -EFAULT; goto done; } @@ -160,6 +160,7 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga drm_ati_pcigart_cleanup(dev, gart_info); address = NULL; bus_address = 0; + ret = -ENOMEM; goto done; } page_base = (u32) entry->busaddr[i]; @@ -188,7 +189,7 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga page_base += ATI_PCIGART_PAGE_SIZE; } } - ret = 1; + ret = 0; #if defined(__i386__) || defined(__x86_64__) wbinvd(); diff --git a/drivers/gpu/drm/r128/r128_cce.c b/drivers/gpu/drm/r128/r128_cce.c index c9890afe69d6..b91af1bf531b 100644 --- a/drivers/gpu/drm/r128/r128_cce.c +++ b/drivers/gpu/drm/r128/r128_cce.c @@ -560,11 +560,12 @@ static int r128_do_init_cce(struct drm_device *dev, drm_r128_init_t *init) dev_priv->gart_info.addr = NULL; dev_priv->gart_info.bus_addr = 0; dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI; - if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) { + rc = drm_ati_pcigart_init(dev, &dev_priv->gart_info); + if (rc) { DRM_ERROR("failed to init PCI GART!\n"); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce(dev); - return -ENOMEM; + return rc; } R128_WRITE(R128_PCI_GART_PAGE, dev_priv->gart_info.bus_addr); #if IS_ENABLED(CONFIG_AGP) From 329e95a7871d8bd52d2f7aabca7daf147a26fdb1 Mon Sep 17 00:00:00 2001 From: emersion Date: Sun, 16 Dec 2018 18:49:08 +0000 Subject: [PATCH 31/49] drm/vkms: set preferred depth to 24 Otherwise DRM_CAP_DUMB_PREFERRED_DEPTH is zero. Signed-off-by: Simon Ser Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/o2SmEP0M6h287Fs5OeL3HtQzTr8uV0PyOhFict_qdxeS7vFvV1Zr8qzRUJh-YnCoJHo13nJgAqqQByzEzTZTqk9R2ExsOszYLj68hQLqBIc=@emersion.fr --- drivers/gpu/drm/vkms/vkms_drv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c index 83087877565c..2a16b86196dc 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.c +++ b/drivers/gpu/drm/vkms/vkms_drv.c @@ -95,6 +95,7 @@ static int vkms_modeset_init(struct vkms_device *vkmsdev) dev->mode_config.min_height = YRES_MIN; dev->mode_config.max_width = XRES_MAX; dev->mode_config.max_height = YRES_MAX; + dev->mode_config.preferred_depth = 24; return vkms_output_init(vkmsdev); } From 93a6788a34956e8ad3115a7acf79c5983edcf9c7 Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Thu, 13 Sep 2018 13:23:00 +0530 Subject: [PATCH 32/49] MAINTAINERS: drm: Remove myself as drm-bridge maintainer I have moved on to other stuff for now. Haven't been able to make time to review bridge related work. Andrzej has been doing it by himself for a while now. Cc: Andrzej Hajda Cc: Laurent Pinchart Cc: Gustavo Padovan Cc: Maarten Lankhorst Cc: Sean Paul Cc: Daniel Vetter Signed-off-by: Archit Taneja Signed-off-by: Andrzej Hajda Link: https://patchwork.freedesktop.org/patch/msgid/20180913075300.22510-1-architt@codeaurora.org --- MAINTAINERS | 1 - 1 file changed, 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 135052797c86..8fe0e762bab0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4850,7 +4850,6 @@ F: Documentation/devicetree/bindings/display/atmel/ T: git git://anongit.freedesktop.org/drm/drm-misc DRM DRIVERS FOR BRIDGE CHIPS -M: Archit Taneja M: Andrzej Hajda R: Laurent Pinchart S: Maintained From 199d035bb84d0c8b7fb1847943729a114e351a84 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 18 Dec 2018 15:00:24 +0900 Subject: [PATCH 33/49] drm: dw-hdmi-i2s: convert to SPDX identifiers This patch updates license to use SPDX-License-Identifier instead of verbose license text. Signed-off-by: Kuninori Morimoto Reviewed-by: Laurent Pinchart Signed-off-by: Andrzej Hajda Link: https://patchwork.freedesktop.org/patch/msgid/87lg4n1izg.wl-kuninori.morimoto.gx@renesas.com --- drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c index 8f9c8a6b46de..2228689d9a5e 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c @@ -1,12 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 /* * dw-hdmi-i2s-audio.c * * Copyright (c) 2017 Renesas Solutions Corp. * Kuninori Morimoto - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #include From eda6887f1961e0d2fb866b1a520b2de5b3828de5 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 6 Dec 2018 15:24:35 +0100 Subject: [PATCH 34/49] drm/connector: Fix drm_mode_create_tv_properties() doc The in the kernel-doc header did not match the function name. Signed-off-by: Boris Brezillon Reviewed-by: Eric Anholt Acked-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20181206142439.10441-2-boris.brezillon@bootlin.com --- drivers/gpu/drm/drm_connector.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index f0dd3315b1b8..32946eff5488 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -1138,7 +1138,7 @@ void drm_hdmi_avi_infoframe_content_type(struct hdmi_avi_infoframe *frame, EXPORT_SYMBOL(drm_hdmi_avi_infoframe_content_type); /** - * drm_create_tv_properties - create TV specific connector properties + * drm_mode_create_tv_properties - create TV specific connector properties * @dev: DRM device * @num_modes: number of different TV formats (modes) supported * @modes: array of pointers to strings containing name of each format From 56406e15b5e83256151ef74eb1a219cbf13d91c8 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 6 Dec 2018 15:24:36 +0100 Subject: [PATCH 35/49] drm/connector: Clarify the unit of TV margins All margins are expressed in pixels. Clarify that in the doc. Signed-off-by: Boris Brezillon Reviewed-by: Eric Anholt Acked-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20181206142439.10441-3-boris.brezillon@bootlin.com --- include/drm/drm_connector.h | 2 +- include/drm/drm_mode_config.h | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 665b9cae7f43..9d28e8180cfd 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -394,7 +394,7 @@ int drm_display_info_set_bus_formats(struct drm_display_info *info, /** * struct drm_tv_connector_state - TV connector related states * @subconnector: selected subconnector - * @margins: margins + * @margins: margins (all margins are expressed in pixels) * @margins.left: left margin * @margins.right: right margin * @margins.top: top margin diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h index 88c536bd9a7b..2bbe91c561a1 100644 --- a/include/drm/drm_mode_config.h +++ b/include/drm/drm_mode_config.h @@ -683,22 +683,22 @@ struct drm_mode_config { struct drm_property *tv_mode_property; /** * @tv_left_margin_property: Optional TV property to set the left - * margin. + * margin (expressed in pixels). */ struct drm_property *tv_left_margin_property; /** * @tv_right_margin_property: Optional TV property to set the right - * margin. + * margin (expressed in pixels). */ struct drm_property *tv_right_margin_property; /** * @tv_top_margin_property: Optional TV property to set the right - * margin. + * margin (expressed in pixels). */ struct drm_property *tv_top_margin_property; /** * @tv_bottom_margin_property: Optional TV property to set the right - * margin. + * margin (expressed in pixels). */ struct drm_property *tv_bottom_margin_property; /** From 6c4f52dca36f5e3e2354c30591d38e92f4657ed9 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 6 Dec 2018 15:24:37 +0100 Subject: [PATCH 36/49] drm/connector: Allow creation of margin props alone TV margins properties can only be added as part of the SDTV TV connector properties creation, but we might need those props for HDMI TVs too, so let's move the margins props creation in a separate function and expose it to drivers. We also add an helper to attach margins props to a connector. Signed-off-by: Boris Brezillon Reviewed-by: Eric Anholt Acked-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20181206142439.10441-4-boris.brezillon@bootlin.com --- drivers/gpu/drm/drm_connector.c | 83 ++++++++++++++++++++++++++------- include/drm/drm_connector.h | 2 + 2 files changed, 67 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 32946eff5488..66b2fd20369a 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -1137,6 +1137,70 @@ void drm_hdmi_avi_infoframe_content_type(struct hdmi_avi_infoframe *frame, } EXPORT_SYMBOL(drm_hdmi_avi_infoframe_content_type); +/** + * drm_mode_attach_tv_margin_properties - attach TV connector margin properties + * @connector: DRM connector + * + * Called by a driver when it needs to attach TV margin props to a connector. + * Typically used on SDTV and HDMI connectors. + */ +void drm_connector_attach_tv_margin_properties(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + + drm_object_attach_property(&connector->base, + dev->mode_config.tv_left_margin_property, + 0); + drm_object_attach_property(&connector->base, + dev->mode_config.tv_right_margin_property, + 0); + drm_object_attach_property(&connector->base, + dev->mode_config.tv_top_margin_property, + 0); + drm_object_attach_property(&connector->base, + dev->mode_config.tv_bottom_margin_property, + 0); +} +EXPORT_SYMBOL(drm_connector_attach_tv_margin_properties); + +/** + * drm_mode_create_tv_margin_properties - create TV connector margin properties + * @dev: DRM device + * + * Called by a driver's HDMI connector initialization routine, this function + * creates the TV margin properties for a given device. No need to call this + * function for an SDTV connector, it's already called from + * drm_mode_create_tv_properties(). + */ +int drm_mode_create_tv_margin_properties(struct drm_device *dev) +{ + if (dev->mode_config.tv_left_margin_property) + return 0; + + dev->mode_config.tv_left_margin_property = + drm_property_create_range(dev, 0, "left margin", 0, 100); + if (!dev->mode_config.tv_left_margin_property) + return -ENOMEM; + + dev->mode_config.tv_right_margin_property = + drm_property_create_range(dev, 0, "right margin", 0, 100); + if (!dev->mode_config.tv_right_margin_property) + return -ENOMEM; + + dev->mode_config.tv_top_margin_property = + drm_property_create_range(dev, 0, "top margin", 0, 100); + if (!dev->mode_config.tv_top_margin_property) + return -ENOMEM; + + dev->mode_config.tv_bottom_margin_property = + drm_property_create_range(dev, 0, "bottom margin", 0, 100); + if (!dev->mode_config.tv_bottom_margin_property) + return -ENOMEM; + + return 0; +} +EXPORT_SYMBOL(drm_mode_create_tv_margin_properties); + /** * drm_mode_create_tv_properties - create TV specific connector properties * @dev: DRM device @@ -1183,24 +1247,7 @@ int drm_mode_create_tv_properties(struct drm_device *dev, /* * Other, TV specific properties: margins & TV modes. */ - dev->mode_config.tv_left_margin_property = - drm_property_create_range(dev, 0, "left margin", 0, 100); - if (!dev->mode_config.tv_left_margin_property) - goto nomem; - - dev->mode_config.tv_right_margin_property = - drm_property_create_range(dev, 0, "right margin", 0, 100); - if (!dev->mode_config.tv_right_margin_property) - goto nomem; - - dev->mode_config.tv_top_margin_property = - drm_property_create_range(dev, 0, "top margin", 0, 100); - if (!dev->mode_config.tv_top_margin_property) - goto nomem; - - dev->mode_config.tv_bottom_margin_property = - drm_property_create_range(dev, 0, "bottom margin", 0, 100); - if (!dev->mode_config.tv_bottom_margin_property) + if (drm_mode_create_tv_margin_properties(dev)) goto nomem; dev->mode_config.tv_mode_property = diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 9d28e8180cfd..594f8d33a61f 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -1238,9 +1238,11 @@ const char *drm_get_tv_select_name(int val); const char *drm_get_content_protection_name(int val); int drm_mode_create_dvi_i_properties(struct drm_device *dev); +int drm_mode_create_tv_margin_properties(struct drm_device *dev); int drm_mode_create_tv_properties(struct drm_device *dev, unsigned int num_modes, const char * const modes[]); +void drm_connector_attach_tv_margin_properties(struct drm_connector *conn); int drm_mode_create_scaling_mode_property(struct drm_device *dev); int drm_connector_attach_content_type_property(struct drm_connector *dev); int drm_connector_attach_scaling_mode_property(struct drm_connector *connector, From 666e73587f90f42d90385c1bea1009a650bf73f4 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 6 Dec 2018 15:24:38 +0100 Subject: [PATCH 37/49] drm/vc4: Take margin setup into account when updating planes Applyin margins is just a matter of scaling all planes appropriately and adjusting the CRTC X/Y offset to account for the left/right/top/bottom borders. Create a vc4_plane_margins_adj() function doing that and call it from vc4_plane_setup_clipping_and_scaling() so that we are ready to attach margins properties to the HDMI connector. Signed-off-by: Boris Brezillon Reviewed-by: Eric Anholt Acked-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20181206142439.10441-5-boris.brezillon@bootlin.com --- drivers/gpu/drm/vc4/vc4_crtc.c | 43 ++++++++++++++++++++++++++++ drivers/gpu/drm/vc4/vc4_drv.h | 3 ++ drivers/gpu/drm/vc4/vc4_plane.c | 50 +++++++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 3ce136ba8791..97caf1671dd0 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -49,6 +49,13 @@ struct vc4_crtc_state { struct drm_mm_node mm; bool feed_txp; bool txp_armed; + + struct { + unsigned int left; + unsigned int right; + unsigned int top; + unsigned int bottom; + } margins; }; static inline struct vc4_crtc_state * @@ -624,6 +631,37 @@ static enum drm_mode_status vc4_crtc_mode_valid(struct drm_crtc *crtc, return MODE_OK; } +void vc4_crtc_get_margins(struct drm_crtc_state *state, + unsigned int *left, unsigned int *right, + unsigned int *top, unsigned int *bottom) +{ + struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(state); + struct drm_connector_state *conn_state; + struct drm_connector *conn; + int i; + + *left = vc4_state->margins.left; + *right = vc4_state->margins.right; + *top = vc4_state->margins.top; + *bottom = vc4_state->margins.bottom; + + /* We have to interate over all new connector states because + * vc4_crtc_get_margins() might be called before + * vc4_crtc_atomic_check() which means margins info in vc4_crtc_state + * might be outdated. + */ + for_each_new_connector_in_state(state->state, conn, conn_state, i) { + if (conn_state->crtc != state->crtc) + continue; + + *left = conn_state->tv.margins.left; + *right = conn_state->tv.margins.right; + *top = conn_state->tv.margins.top; + *bottom = conn_state->tv.margins.bottom; + break; + } +} + static int vc4_crtc_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state) { @@ -671,6 +709,10 @@ static int vc4_crtc_atomic_check(struct drm_crtc *crtc, vc4_state->feed_txp = false; } + vc4_state->margins.left = conn_state->tv.margins.left; + vc4_state->margins.right = conn_state->tv.margins.right; + vc4_state->margins.top = conn_state->tv.margins.top; + vc4_state->margins.bottom = conn_state->tv.margins.bottom; break; } @@ -972,6 +1014,7 @@ static struct drm_crtc_state *vc4_crtc_duplicate_state(struct drm_crtc *crtc) old_vc4_state = to_vc4_crtc_state(crtc->state); vc4_state->feed_txp = old_vc4_state->feed_txp; + vc4_state->margins = old_vc4_state->margins; __drm_atomic_helper_crtc_duplicate_state(crtc, &vc4_state->base); return &vc4_state->base; diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index 4f87b03f837d..c24b078f0593 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -707,6 +707,9 @@ bool vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id, const struct drm_display_mode *mode); void vc4_crtc_handle_vblank(struct vc4_crtc *crtc); void vc4_crtc_txp_armed(struct drm_crtc_state *state); +void vc4_crtc_get_margins(struct drm_crtc_state *state, + unsigned int *right, unsigned int *left, + unsigned int *top, unsigned int *bottom); /* vc4_debugfs.c */ int vc4_debugfs_init(struct drm_minor *minor); diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index 283abd7d1e9b..2901ed0c5223 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -258,6 +258,52 @@ static u32 vc4_get_scl_field(struct drm_plane_state *state, int plane) } } +static int vc4_plane_margins_adj(struct drm_plane_state *pstate) +{ + struct vc4_plane_state *vc4_pstate = to_vc4_plane_state(pstate); + unsigned int left, right, top, bottom, adjhdisplay, adjvdisplay; + struct drm_crtc_state *crtc_state; + + crtc_state = drm_atomic_get_new_crtc_state(pstate->state, + pstate->crtc); + + vc4_crtc_get_margins(crtc_state, &left, &right, &top, &bottom); + if (!left && !right && !top && !bottom) + return 0; + + if (left + right >= crtc_state->mode.hdisplay || + top + bottom >= crtc_state->mode.vdisplay) + return -EINVAL; + + adjhdisplay = crtc_state->mode.hdisplay - (left + right); + vc4_pstate->crtc_x = DIV_ROUND_CLOSEST(vc4_pstate->crtc_x * + adjhdisplay, + crtc_state->mode.hdisplay); + vc4_pstate->crtc_x += left; + if (vc4_pstate->crtc_x > crtc_state->mode.hdisplay - left) + vc4_pstate->crtc_x = crtc_state->mode.hdisplay - left; + + adjvdisplay = crtc_state->mode.vdisplay - (top + bottom); + vc4_pstate->crtc_y = DIV_ROUND_CLOSEST(vc4_pstate->crtc_y * + adjvdisplay, + crtc_state->mode.vdisplay); + vc4_pstate->crtc_y += top; + if (vc4_pstate->crtc_y > crtc_state->mode.vdisplay - top) + vc4_pstate->crtc_y = crtc_state->mode.vdisplay - top; + + vc4_pstate->crtc_w = DIV_ROUND_CLOSEST(vc4_pstate->crtc_w * + adjhdisplay, + crtc_state->mode.hdisplay); + vc4_pstate->crtc_h = DIV_ROUND_CLOSEST(vc4_pstate->crtc_h * + adjvdisplay, + crtc_state->mode.vdisplay); + + if (!vc4_pstate->crtc_w || !vc4_pstate->crtc_h) + return -EINVAL; + + return 0; +} + static int vc4_plane_setup_clipping_and_scaling(struct drm_plane_state *state) { struct vc4_plane_state *vc4_state = to_vc4_plane_state(state); @@ -306,6 +352,10 @@ static int vc4_plane_setup_clipping_and_scaling(struct drm_plane_state *state) vc4_state->crtc_w = state->dst.x2 - state->dst.x1; vc4_state->crtc_h = state->dst.y2 - state->dst.y1; + ret = vc4_plane_margins_adj(state); + if (ret) + return ret; + vc4_state->x_scaling[0] = vc4_get_scaling_mode(vc4_state->src_w[0], vc4_state->crtc_w); vc4_state->y_scaling[0] = vc4_get_scaling_mode(vc4_state->src_h[0], From db999538fdb0679629d90652f8a1437df1e85a7d Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Thu, 6 Dec 2018 15:24:39 +0100 Subject: [PATCH 38/49] drm/vc4: Attach margin props to the HDMI connector Now that the plane code takes the margins setup into account, we can safely attach margin props to the HDMI connector. We also take care of filling AVI infoframes correctly to expose the top/botton/left/right bar. Note that those margin props match pretty well the overscan_{left,right,top,bottom} properties defined in config.txt and parsed by the VC4 firmware. Signed-off-by: Boris Brezillon Reviewed-by: Eric Anholt Acked-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20181206142439.10441-6-boris.brezillon@bootlin.com --- drivers/gpu/drm/vc4/vc4_hdmi.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index fd5522fd179e..2f276222e30f 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -310,6 +310,7 @@ static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev, { struct drm_connector *connector; struct vc4_hdmi_connector *hdmi_connector; + int ret; hdmi_connector = devm_kzalloc(dev->dev, sizeof(*hdmi_connector), GFP_KERNEL); @@ -323,6 +324,13 @@ static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev, DRM_MODE_CONNECTOR_HDMIA); drm_connector_helper_add(connector, &vc4_hdmi_connector_helper_funcs); + /* Create and attach TV margin props to this connector. */ + ret = drm_mode_create_tv_margin_properties(dev); + if (ret) + return ERR_PTR(ret); + + drm_connector_attach_tv_margin_properties(connector); + connector->polled = (DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT); @@ -408,6 +416,9 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder, static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder) { struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); + struct vc4_dev *vc4 = encoder->dev->dev_private; + struct vc4_hdmi *hdmi = vc4->hdmi; + struct drm_connector_state *cstate = hdmi->connector->state; struct drm_crtc *crtc = encoder->crtc; const struct drm_display_mode *mode = &crtc->state->adjusted_mode; union hdmi_infoframe frame; @@ -426,6 +437,11 @@ static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder) vc4_encoder->rgb_range_selectable, false); + frame.avi.right_bar = cstate->tv.margins.right; + frame.avi.left_bar = cstate->tv.margins.left; + frame.avi.top_bar = cstate->tv.margins.top; + frame.avi.bottom_bar = cstate->tv.margins.bottom; + vc4_hdmi_write_infoframe(encoder, &frame); } From 70bce993a7aa57c00798d8f13ebbbddd81cbbef9 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 20 Dec 2018 11:11:21 +0100 Subject: [PATCH 39/49] drm/bochs: add edid present check Check header before trying to read the complete edid blob, to avoid the log being spammed in case qemu has no edid support (old qemu or edid support turned off). Fixes: 01f23459cf drm/bochs: add edid support. Signed-off-by: Gerd Hoffmann Reviewed-by: Daniel Vetter Reviewed-by: Oleksandr Andrushchenko Link: http://patchwork.freedesktop.org/patch/msgid/20181220101122.16153-1-kraxel@redhat.com --- drivers/gpu/drm/bochs/bochs_hw.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/bochs/bochs_hw.c b/drivers/gpu/drm/bochs/bochs_hw.c index c90a0d492fd5..d0b4e1cee83e 100644 --- a/drivers/gpu/drm/bochs/bochs_hw.c +++ b/drivers/gpu/drm/bochs/bochs_hw.c @@ -86,9 +86,16 @@ static int bochs_get_edid_block(void *data, u8 *buf, int bochs_hw_load_edid(struct bochs_device *bochs) { + u8 header[8]; + if (!bochs->mmio) return -1; + /* check header to detect whenever edid support is enabled in qemu */ + bochs_get_edid_block(bochs, header, 0, ARRAY_SIZE(header)); + if (drm_edid_header_is_valid(header) != 8) + return -1; + kfree(bochs->edid); bochs->edid = drm_do_get_edid(&bochs->connector, bochs_get_edid_block, bochs); From 2674305a1f5a5356e3c4488d90aab2654142ee99 Mon Sep 17 00:00:00 2001 From: Yangtao Li Date: Fri, 30 Nov 2018 11:11:01 -0500 Subject: [PATCH 40/49] dma-buf: Change to use DEFINE_SHOW_ATTRIBUTE macro Use DEFINE_SHOW_ATTRIBUTE macro to simplify the code. Signed-off-by: Yangtao Li Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20181130161101.3413-1-tiny.windzz@gmail.com --- drivers/dma-buf/dma-buf.c | 12 +----------- drivers/dma-buf/sync_debug.c | 16 +++------------- 2 files changed, 4 insertions(+), 24 deletions(-) diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c index 02f7f9a89979..7c858020d14b 100644 --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c @@ -1093,17 +1093,7 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused) return 0; } -static int dma_buf_debug_open(struct inode *inode, struct file *file) -{ - return single_open(file, dma_buf_debug_show, NULL); -} - -static const struct file_operations dma_buf_debug_fops = { - .open = dma_buf_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; +DEFINE_SHOW_ATTRIBUTE(dma_buf_debug); static struct dentry *dma_buf_debugfs_dir; diff --git a/drivers/dma-buf/sync_debug.c b/drivers/dma-buf/sync_debug.c index c4c8ecb24aa9..c0abf37df88b 100644 --- a/drivers/dma-buf/sync_debug.c +++ b/drivers/dma-buf/sync_debug.c @@ -147,7 +147,7 @@ static void sync_print_sync_file(struct seq_file *s, } } -static int sync_debugfs_show(struct seq_file *s, void *unused) +static int sync_info_debugfs_show(struct seq_file *s, void *unused) { struct list_head *pos; @@ -178,17 +178,7 @@ static int sync_debugfs_show(struct seq_file *s, void *unused) return 0; } -static int sync_info_debugfs_open(struct inode *inode, struct file *file) -{ - return single_open(file, sync_debugfs_show, inode->i_private); -} - -static const struct file_operations sync_info_debugfs_fops = { - .open = sync_info_debugfs_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; +DEFINE_SHOW_ATTRIBUTE(sync_info_debugfs); static __init int sync_debugfs_init(void) { @@ -218,7 +208,7 @@ void sync_dump(void) }; int i; - sync_debugfs_show(&s, NULL); + sync_info_debugfs_show(&s, NULL); for (i = 0; i < s.count; i += DUMP_CHUNK) { if ((s.count - i) > DUMP_CHUNK) { From 183d9dc49572718d1f2b943d0bdea039a90f766d Mon Sep 17 00:00:00 2001 From: Brajeswar Ghosh Date: Mon, 24 Dec 2018 20:06:36 +0530 Subject: [PATCH 41/49] drm/drm_drv.c: Remove duplicate header Remove drm_crtc_internal.h which is included more than once Signed-off-by: Brajeswar Ghosh Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20181224143636.GA3237@hp-pavilion-15-notebook-pc-brajeswar --- drivers/gpu/drm/drm_drv.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 12e5e2be7890..a5fe91b8c3c9 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -41,7 +41,6 @@ #include "drm_crtc_internal.h" #include "drm_legacy.h" #include "drm_internal.h" -#include "drm_crtc_internal.h" /* * drm_debug: Enable debug output. From ecb2e2fd5a442e8639b9648df54b77a32ca4c906 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Wed, 26 Dec 2018 22:03:47 +0100 Subject: [PATCH 42/49] drm: move DRM_IF_VERSION to drm_internal.h Move DRM_IF_VERSION out of drmP.h to allow users to get rid of the drmP include. Signed-off-by: Sam Ravnborg Cc: Maarten Lankhorst Cc: Maxime Ripard Cc: Sean Paul Cc: David Airlie Cc: Daniel Vetter Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20181226210353.13993-1-sam@ravnborg.org --- drivers/gpu/drm/drm_internal.h | 2 ++ include/drm/drmP.h | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h index c7a7d7ce5d1c..331112b2ae88 100644 --- a/drivers/gpu/drm/drm_internal.h +++ b/drivers/gpu/drm/drm_internal.h @@ -26,6 +26,8 @@ #define DRM_IF_MAJOR 1 #define DRM_IF_MINOR 4 +#define DRM_IF_VERSION(maj, min) (maj << 16 | min) + struct drm_prime_file_private; struct dma_buf; diff --git a/include/drm/drmP.h b/include/drm/drmP.h index bdb0d5548f39..db94ef00940e 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -94,8 +94,6 @@ struct dma_buf_attachment; struct pci_dev; struct pci_controller; -#define DRM_IF_VERSION(maj, min) (maj << 16 | min) - #define DRM_SWITCH_POWER_ON 0 #define DRM_SWITCH_POWER_OFF 1 #define DRM_SWITCH_POWER_CHANGING 2 From c76426883c8f44bc7d2aee123e28867c67b87384 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 28 Dec 2018 15:04:46 +0200 Subject: [PATCH 43/49] drm: un-inline drm_legacy_findmap() Un-inline drm_legacy_findmap() to not depend on struct drm_device definition within drm_legacy.h, so that a forward declaration suffices. Also include drm_hashtab.h in drm_legacy.h to make it more self-contained. Make it easier to drop drmP.h includes. v2: avoid including drm_device.h by un-inlining (Daniel) [Updated commit message per Laurent's review while applying.] Cc: Sam Ravnborg Cc: Daniel Vetter Cc: Laurent Pinchart Reviewed-by: Daniel Vetter Reviewed-by: Laurent Pinchart Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20181228130446.22141-1-jani.nikula@intel.com --- drivers/gpu/drm/drm_bufs.c | 11 +++++++++++ include/drm/drm_legacy.h | 14 ++++---------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c index d7d10cabb9bb..a39ab2193bfe 100644 --- a/drivers/gpu/drm/drm_bufs.c +++ b/drivers/gpu/drm/drm_bufs.c @@ -377,6 +377,17 @@ int drm_legacy_addmap(struct drm_device *dev, resource_size_t offset, } EXPORT_SYMBOL(drm_legacy_addmap); +struct drm_local_map *drm_legacy_findmap(struct drm_device *dev, + unsigned int token) +{ + struct drm_map_list *_entry; + list_for_each_entry(_entry, &dev->maplist, head) + if (_entry->user_token == token) + return _entry->map; + return NULL; +} +EXPORT_SYMBOL(drm_legacy_findmap); + /** * Ioctl to specify a range of memory that is available for mapping by a * non-root process. diff --git a/include/drm/drm_legacy.h b/include/drm/drm_legacy.h index 8fad66f88e4f..3e99ab69c122 100644 --- a/include/drm/drm_legacy.h +++ b/include/drm/drm_legacy.h @@ -2,6 +2,9 @@ #define __DRM_DRM_LEGACY_H__ #include +#include + +struct drm_device; /* * Legacy driver interfaces for the Direct Rendering Manager @@ -156,6 +159,7 @@ struct drm_map_list { int drm_legacy_addmap(struct drm_device *d, resource_size_t offset, unsigned int size, enum drm_map_type type, enum drm_map_flags flags, struct drm_local_map **map_p); +struct drm_local_map *drm_legacy_findmap(struct drm_device *dev, unsigned int token); void drm_legacy_rmmap(struct drm_device *d, struct drm_local_map *map); int drm_legacy_rmmap_locked(struct drm_device *d, struct drm_local_map *map); void drm_legacy_master_rmmaps(struct drm_device *dev, @@ -194,14 +198,4 @@ void drm_legacy_ioremap(struct drm_local_map *map, struct drm_device *dev); void drm_legacy_ioremap_wc(struct drm_local_map *map, struct drm_device *dev); void drm_legacy_ioremapfree(struct drm_local_map *map, struct drm_device *dev); -static inline struct drm_local_map *drm_legacy_findmap(struct drm_device *dev, - unsigned int token) -{ - struct drm_map_list *_entry; - list_for_each_entry(_entry, &dev->maplist, head) - if (_entry->user_token == token) - return _entry->map; - return NULL; -} - #endif /* __DRM_DRM_LEGACY_H__ */ From 5c27b9fafeadc919fd58a3b4fbd718a1cb7b1b1a Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 27 Dec 2018 14:56:37 +0200 Subject: [PATCH 44/49] drm: include kernel.h and agp_backend.h from intel-gtt.h intel-gtt.h uses kernel and agp pointers, make it self-contained by including the relevant headers. This prepares for dropping drmP.h from files including intel-gtt.h. [Updated commit message per Laurent's review while applying.] Cc: Sam Ravnborg Cc: Daniel Vetter Cc: Laurent Pinchart Reviewed-by: Daniel Vetter Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/9414800f89d6f326c6e9173233bf6c4dee254d9a.1545915059.git.jani.nikula@intel.com --- include/drm/intel-gtt.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/drm/intel-gtt.h b/include/drm/intel-gtt.h index 2324c84a25c0..71d81923e6b0 100644 --- a/include/drm/intel-gtt.h +++ b/include/drm/intel-gtt.h @@ -4,6 +4,9 @@ #ifndef _DRM_INTEL_GTT_H #define _DRM_INTEL_GTT_H +#include +#include + void intel_gtt_get(u64 *gtt_total, phys_addr_t *mappable_base, resource_size_t *mappable_end); From 39e23674809b0fab008e32c268d7c5ef4a019c8b Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 27 Dec 2018 14:56:38 +0200 Subject: [PATCH 45/49] drm: include idr.h from drm_file.h drm_file.h embeds idr structures in DRM-specific structures. Include the corresponding header to make drm_file.h self-contained. Make it easier to drop drmP.h includes. [Updated commit message per Laurent's review while applying.] Cc: Sam Ravnborg Cc: Daniel Vetter Cc: Laurent Pinchart Reviewed-by: Daniel Vetter Reviewed-by: Laurent Pinchart Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/2818b15332ab562722dfc324cf977b7eb4a04401.1545915059.git.jani.nikula@intel.com --- include/drm/drm_file.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/drm/drm_file.h b/include/drm/drm_file.h index 84ac79219e4c..6710b612e2f6 100644 --- a/include/drm/drm_file.h +++ b/include/drm/drm_file.h @@ -32,6 +32,7 @@ #include #include +#include #include From f7e271de230b20ea3f9cecf71c45ca23c58aa055 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 27 Dec 2018 14:56:39 +0200 Subject: [PATCH 46/49] drm: include types.h from drm_hdcp.h drm_hdcp.h uses kernel integer types, make it self-contained by including linux/kernel.h. This prepares for dropping drmP.h from files including drm_hdcp.h. [Updated commit message per Laurent's review while applying.] Cc: Sam Ravnborg Cc: Daniel Vetter Cc: Laurent Pinchart Reviewed-by: Daniel Vetter Reviewed-by: Laurent Pinchart Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/adfc79941e827b49eb6186f317cbeff0fb365f33.1545915059.git.jani.nikula@intel.com --- include/drm/drm_hdcp.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/drm/drm_hdcp.h b/include/drm/drm_hdcp.h index a6de09c5e47f..d6dfef8cff6a 100644 --- a/include/drm/drm_hdcp.h +++ b/include/drm/drm_hdcp.h @@ -9,6 +9,8 @@ #ifndef _DRM_HDCP_H_INCLUDED_ #define _DRM_HDCP_H_INCLUDED_ +#include + /* Period of hdcp checks (to ensure we're still authenticated) */ #define DRM_HDCP_CHECK_PERIOD_MS (128 * 16) From dd7ece7f6e220e4d1a2a8ba4c42622d7d73e6376 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 28 Dec 2018 10:28:15 +0200 Subject: [PATCH 47/49] drm: forward declare struct drm_file in drm_syncobj.h drm_syncobj.h uses struct drm_file pointers, forward declare struct drm_file to make the header self-contained. This prepares for dropping drmP.h from files including drm_syncobj.h. Switch from "" to <> includes while at it. v2: forward declare instead of including drm_file.h (Daniel) [Updated commit message per Laurent's review while applying.] Cc: Sam Ravnborg Cc: Daniel Vetter Cc: Laurent Pinchart Reviewed-by: Daniel Vetter Reviewed-by: Laurent Pinchart Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20181228082815.10797-1-jani.nikula@intel.com --- include/drm/drm_syncobj.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/drm/drm_syncobj.h b/include/drm/drm_syncobj.h index 29244cbcd05e..ef5721512632 100644 --- a/include/drm/drm_syncobj.h +++ b/include/drm/drm_syncobj.h @@ -26,7 +26,9 @@ #ifndef __DRM_SYNCOBJ_H__ #define __DRM_SYNCOBJ_H__ -#include "linux/dma-fence.h" +#include + +struct drm_file; struct drm_syncobj_cb; From 227ad6d957898a88b1746e30234ece64d305f066 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 30 Dec 2018 12:28:42 +0000 Subject: [PATCH 48/49] drm: Reorder set_property_atomic to avoid returning with an active ww_ctx Delay the drm_modeset_acquire_init() until after we check for an allocation failure so that we can return immediately upon error without having to unwind. WARNING: lock held when returning to user space! 4.20.0+ #174 Not tainted ------------------------------------------------ syz-executor556/8153 is leaving the kernel with locks still held! 1 lock held by syz-executor556/8153: #0: 000000005100c85c (crtc_ww_class_acquire){+.+.}, at: set_property_atomic+0xb3/0x330 drivers/gpu/drm/drm_mode_object.c:462 Reported-by: syzbot+6ea337c427f5083ebdf2@syzkaller.appspotmail.com Fixes: 144a7999d633 ("drm: Handle properties in the core for atomic drivers") Signed-off-by: Chris Wilson Cc: Daniel Vetter Cc: Maarten Lankhorst Cc: Sean Paul Cc: David Airlie Cc: # v4.14+ Reviewed-by: Maarten Lankhorst Link: https://patchwork.freedesktop.org/patch/msgid/20181230122842.21917-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/drm_mode_object.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_mode_object.c b/drivers/gpu/drm/drm_mode_object.c index bb1dd46496cd..a9005c1c2384 100644 --- a/drivers/gpu/drm/drm_mode_object.c +++ b/drivers/gpu/drm/drm_mode_object.c @@ -459,12 +459,13 @@ static int set_property_atomic(struct drm_mode_object *obj, struct drm_modeset_acquire_ctx ctx; int ret; - drm_modeset_acquire_init(&ctx, 0); - state = drm_atomic_state_alloc(dev); if (!state) return -ENOMEM; + + drm_modeset_acquire_init(&ctx, 0); state->acquire_ctx = &ctx; + retry: if (prop == state->dev->mode_config.dpms_property) { if (obj->type != DRM_MODE_OBJECT_CONNECTOR) { From c39191feed4540fed98badeb484833dcf659bb96 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 29 Dec 2018 10:49:07 +0800 Subject: [PATCH 49/49] drm: Fix error handling in drm_legacy_addctx 'ctx->handle' is unsigned, it never less than zero. This patch use int 'tmp_handle' to handle the err condition. Fixes: 62968144e673 ("drm: convert drm context code to use Linux idr") Signed-off-by: YueHaibing Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20181229024907.12852-1-yuehaibing@huawei.com --- drivers/gpu/drm/drm_context.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/drm_context.c b/drivers/gpu/drm/drm_context.c index 506663c69b0a..6e8e1a9fcae3 100644 --- a/drivers/gpu/drm/drm_context.c +++ b/drivers/gpu/drm/drm_context.c @@ -361,23 +361,26 @@ int drm_legacy_addctx(struct drm_device *dev, void *data, { struct drm_ctx_list *ctx_entry; struct drm_ctx *ctx = data; + int tmp_handle; if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && !drm_core_check_feature(dev, DRIVER_LEGACY)) return -EOPNOTSUPP; - ctx->handle = drm_legacy_ctxbitmap_next(dev); - if (ctx->handle == DRM_KERNEL_CONTEXT) { + tmp_handle = drm_legacy_ctxbitmap_next(dev); + if (tmp_handle == DRM_KERNEL_CONTEXT) { /* Skip kernel's context and get a new one. */ - ctx->handle = drm_legacy_ctxbitmap_next(dev); + tmp_handle = drm_legacy_ctxbitmap_next(dev); } - DRM_DEBUG("%d\n", ctx->handle); - if (ctx->handle < 0) { + DRM_DEBUG("%d\n", tmp_handle); + if (tmp_handle < 0) { DRM_DEBUG("Not enough free contexts.\n"); /* Should this return -EBUSY instead? */ - return -ENOMEM; + return tmp_handle; } + ctx->handle = tmp_handle; + ctx_entry = kmalloc(sizeof(*ctx_entry), GFP_KERNEL); if (!ctx_entry) { DRM_DEBUG("out of memory\n");