[PATCH v2] drm/amdkfd: use time_is_before_jiffies(a + b) to replace "jiffies - a > b"
time_is_before_jiffies deals with timer wrapping correctly. Signed-off-by: Yu Zhe --- drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c b/drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c index a9466d154395..34772fe74296 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c @@ -146,7 +146,7 @@ static void interrupt_wq(struct work_struct *work) struct kfd_dev *dev = container_of(work, struct kfd_dev, interrupt_work); uint32_t ih_ring_entry[KFD_MAX_RING_ENTRY_SIZE]; - long start_jiffies = jiffies; + unsigned long start_jiffies = jiffies; if (dev->device_info.ih_ring_entry_size > sizeof(ih_ring_entry)) { dev_err_once(dev->adev->dev, "Ring entry too small\n"); @@ -156,7 +156,7 @@ static void interrupt_wq(struct work_struct *work) while (dequeue_ih_ring_entry(dev, ih_ring_entry)) { dev->device_info.event_interrupt_class->interrupt_wq(dev, ih_ring_entry); - if (jiffies - start_jiffies > HZ) { + if (time_is_before_jiffies(start_jiffies + HZ)) { /* If we spent more than a second processing signals, * reschedule the worker to avoid soft-lockup warnings */ -- 2.11.0
Re: [PATCH] dma-buf: Fix one use-after-free of fence
Did this ever land? I don't see it in drm-misc. Alex On Thu, Jul 7, 2022 at 4:05 AM Christian König wrote: > > Am 07.07.22 um 10:02 schrieb xinhui pan: > > Need get the new fence when we replace the old one. > > > > Fixes: 047a1b877ed48 ("dma-buf & drm/amdgpu: remove dma_resv workaround") > > Signed-off-by: xinhui pan > > Good catch, Reviewed-by: Christian König > > Going to push that in a minute. > > Christian. > > > --- > > drivers/dma-buf/dma-resv.c | 2 +- > > 1 file changed, 1 insertion(+), 1 deletion(-) > > > > diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c > > index 0cce6e4ec946..205acb2c744d 100644 > > --- a/drivers/dma-buf/dma-resv.c > > +++ b/drivers/dma-buf/dma-resv.c > > @@ -343,7 +343,7 @@ void dma_resv_replace_fences(struct dma_resv *obj, > > uint64_t context, > > if (old->context != context) > > continue; > > > > - dma_resv_list_set(list, i, replacement, usage); > > + dma_resv_list_set(list, i, dma_fence_get(replacement), usage); > > dma_fence_put(old); > > } > > } >
Re: [PATCH 5/6] drm/i915/guc: Support larger contexts on newer hardware
On 7/27/2022 19:42, john.c.harri...@intel.com wrote: From: Matthew Brost The GuC needs a copy of a golden context for implementing watchdog resets (aka media resets). This context is larger on newer platforms. So adjust the size being allocated/copied accordingly. Signed-off-by: Matthew Brost Signed-off-by: John Harrison Reviewed-by: John Harrison --- drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c | 10 +++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c index ba7541f3ca610..74cbe8eaf5318 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c @@ -464,7 +464,11 @@ static void fill_engine_enable_masks(struct intel_gt *gt, } #define LR_HW_CONTEXT_SIZE (80 * sizeof(u32)) -#define LRC_SKIP_SIZE (LRC_PPHWSP_SZ * PAGE_SIZE + LR_HW_CONTEXT_SIZE) +#define XEHP_LR_HW_CONTEXT_SIZE (96 * sizeof(u32)) +#define LR_HW_CONTEXT_SZ(i915) (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50) ? \ + XEHP_LR_HW_CONTEXT_SIZE : \ + LR_HW_CONTEXT_SIZE) +#define LRC_SKIP_SIZE(i915) (LRC_PPHWSP_SZ * PAGE_SIZE + LR_HW_CONTEXT_SZ(i915)) static int guc_prep_golden_context(struct intel_guc *guc) { struct intel_gt *gt = guc_to_gt(guc); @@ -525,7 +529,7 @@ static int guc_prep_golden_context(struct intel_guc *guc) * on all engines). */ ads_blob_write(guc, ads.eng_state_size[guc_class], - real_size - LRC_SKIP_SIZE); + real_size - LRC_SKIP_SIZE(gt->i915)); ads_blob_write(guc, ads.golden_context_lrca[guc_class], addr_ggtt); @@ -599,7 +603,7 @@ static void guc_init_golden_context(struct intel_guc *guc) } GEM_BUG_ON(ads_blob_read(guc, ads.eng_state_size[guc_class]) != - real_size - LRC_SKIP_SIZE); + real_size - LRC_SKIP_SIZE(gt->i915)); GEM_BUG_ON(ads_blob_read(guc, ads.golden_context_lrca[guc_class]) != addr_ggtt); addr_ggtt += alloc_size;
Re: [PATCH 2/6] drm/i915/guc: Fix issues with live_preempt_cancel
On 7/27/2022 19:42, john.c.harri...@intel.com wrote: From: Matthew Brost Having semaphores results in different behavior when a dependent request is cancelled. In the case of semaphores the request could be on the HW and complete successfully while without the request is held in the driver and the error from the dependent request is propagated. Fix live_preempt_cancel to take this behavior into account. Also update live_preempt_cancel to use new function intel_context_ban rather than intel_context_set_banned. Signed-off-by: Matthew Brost Signed-off-by: John Harrison Reviewed-by: John Harrison --- drivers/gpu/drm/i915/gt/selftest_execlists.c | 16 +++- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/selftest_execlists.c b/drivers/gpu/drm/i915/gt/selftest_execlists.c index 02fc97a0ab502..015f8cd3463e2 100644 --- a/drivers/gpu/drm/i915/gt/selftest_execlists.c +++ b/drivers/gpu/drm/i915/gt/selftest_execlists.c @@ -2087,7 +2087,7 @@ static int __cancel_active0(struct live_preempt_cancel *arg) goto out; } - intel_context_set_banned(rq->context); + intel_context_ban(rq->context, rq); err = intel_engine_pulse(arg->engine); if (err) goto out; @@ -2146,7 +2146,7 @@ static int __cancel_active1(struct live_preempt_cancel *arg) if (err) goto out; - intel_context_set_banned(rq[1]->context); + intel_context_ban(rq[1]->context, rq[1]); err = intel_engine_pulse(arg->engine); if (err) goto out; @@ -2229,7 +2229,7 @@ static int __cancel_queued(struct live_preempt_cancel *arg) if (err) goto out; - intel_context_set_banned(rq[2]->context); + intel_context_ban(rq[2]->context, rq[2]); err = intel_engine_pulse(arg->engine); if (err) goto out; @@ -2244,7 +2244,13 @@ static int __cancel_queued(struct live_preempt_cancel *arg) goto out; } - if (rq[1]->fence.error != 0) { + /* +* The behavior between having semaphores and not is different. With +* semaphores the subsequent request is on the hardware and not cancelled +* while without the request is held in the driver and cancelled. +*/ + if (intel_engine_has_semaphores(rq[1]->engine) && + rq[1]->fence.error != 0) { pr_err("Normal inflight1 request did not complete\n"); err = -EINVAL; goto out; @@ -2292,7 +2298,7 @@ static int __cancel_hostile(struct live_preempt_cancel *arg) goto out; } - intel_context_set_banned(rq->context); + intel_context_ban(rq->context, rq); err = intel_engine_pulse(arg->engine); /* force reset */ if (err) goto out;
[PATCH 3/6] drm/i915/guc: Add selftest for a hung GuC
From: Rahul Kumar Singh Add a test to check that the hangcheck will recover from a submission hang in the GuC. Signed-off-by: Rahul Kumar Singh Signed-off-by: John Harrison --- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 1 + .../drm/i915/gt/uc/selftest_guc_hangcheck.c | 159 ++ .../drm/i915/selftests/i915_live_selftests.h | 1 + 3 files changed, 161 insertions(+) create mode 100644 drivers/gpu/drm/i915/gt/uc/selftest_guc_hangcheck.c diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index 0b8c6450fa344..ff205c4125857 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -5177,4 +5177,5 @@ bool intel_guc_virtual_engine_has_heartbeat(const struct intel_engine_cs *ve) #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) #include "selftest_guc.c" #include "selftest_guc_multi_lrc.c" +#include "selftest_guc_hangcheck.c" #endif diff --git a/drivers/gpu/drm/i915/gt/uc/selftest_guc_hangcheck.c b/drivers/gpu/drm/i915/gt/uc/selftest_guc_hangcheck.c new file mode 100644 index 0..af913c4b09d37 --- /dev/null +++ b/drivers/gpu/drm/i915/gt/uc/selftest_guc_hangcheck.c @@ -0,0 +1,159 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright �� 2019 Intel Corporation + */ + +#include "selftests/igt_spinner.h" +#include "selftests/igt_reset.h" +#include "selftests/intel_scheduler_helpers.h" +#include "gt/intel_engine_heartbeat.h" +#include "gem/selftests/mock_context.h" + +#define BEAT_INTERVAL 100 + +static struct i915_request *nop_request(struct intel_engine_cs *engine) +{ + struct i915_request *rq; + + rq = intel_engine_create_kernel_request(engine); + if (IS_ERR(rq)) + return rq; + + i915_request_get(rq); + i915_request_add(rq); + + return rq; +} + +static int intel_hang_guc(void *arg) +{ + struct intel_gt *gt = arg; + int ret = 0; + struct i915_gem_context *ctx; + struct intel_context *ce; + struct igt_spinner spin; + struct i915_request *rq; + intel_wakeref_t wakeref; + struct i915_gpu_error *global = >i915->gpu_error; + struct intel_engine_cs *engine; + unsigned int reset_count; + u32 guc_status; + u32 old_beat; + + ctx = kernel_context(gt->i915, NULL); + if (IS_ERR(ctx)) { + pr_err("Failed get kernel context: %ld\n", PTR_ERR(ctx)); + return PTR_ERR(ctx); + } + + wakeref = intel_runtime_pm_get(gt->uncore->rpm); + + ce = intel_context_create(gt->engine[BCS0]); + if (IS_ERR(ce)) { + ret = PTR_ERR(ce); + pr_err("Failed to create spinner request: %d\n", ret); + goto err; + } + + engine = ce->engine; + reset_count = i915_reset_count(global); + + old_beat = engine->props.heartbeat_interval_ms; + ret = intel_engine_set_heartbeat(engine, BEAT_INTERVAL); + if (ret) { + pr_err("Failed to boost heatbeat interval: %d\n", ret); + goto err; + } + + ret = igt_spinner_init(, engine->gt); + if (ret) { + pr_err("Failed to create spinner: %d\n", ret); + goto err; + } + + rq = igt_spinner_create_request(, ce, MI_NOOP); + intel_context_put(ce); + if (IS_ERR(rq)) { + ret = PTR_ERR(rq); + pr_err("Failed to create spinner request: %d\n", ret); + goto err_spin; + } + + ret = request_add_spin(rq, ); + if (ret) { + i915_request_put(rq); + pr_err("Failed to add Spinner request: %d\n", ret); + goto err_spin; + } + + ret = intel_reset_guc(gt); + if (ret) { + i915_request_put(rq); + pr_err("Failed to reset GuC, ret = %d\n", ret); + goto err_spin; + } + + guc_status = intel_uncore_read(gt->uncore, GUC_STATUS); + if (!(guc_status & GS_MIA_IN_RESET)) { + i915_request_put(rq); + pr_err("GuC failed to reset: status = 0x%08X\n", guc_status); + ret = -EIO; + goto err_spin; + } + + /* Wait for the heartbeat to cause a reset */ + ret = intel_selftest_wait_for_rq(rq); + i915_request_put(rq); + if (ret) { + pr_err("Request failed to complete: %d\n", ret); + goto err_spin; + } + + if (i915_reset_count(global) == reset_count) { + pr_err("Failed to record a GPU reset\n"); + ret = -EINVAL; + goto err_spin; + } + +err_spin: + igt_spinner_end(); + igt_spinner_fini(); + intel_engine_set_heartbeat(engine, old_beat); + + if (ret == 0) { + rq = nop_request(engine); + if (IS_ERR(rq)) { + ret = PTR_ERR(rq); +
[PATCH 4/6] drm/i915/selftest: Cope with not having an RCS engine
From: John Harrison It is no longer guaranteed that there will always be an RCS engine. So, use the helper function for finding the first available engine that can be used for general purpose selftets. Signed-off-by: John Harrison Reviewed-by: Matthew Brost --- drivers/gpu/drm/i915/gt/selftest_hangcheck.c | 12 +--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/selftest_hangcheck.c b/drivers/gpu/drm/i915/gt/selftest_hangcheck.c index 6493265d5f642..7f3bb1d34dfbf 100644 --- a/drivers/gpu/drm/i915/gt/selftest_hangcheck.c +++ b/drivers/gpu/drm/i915/gt/selftest_hangcheck.c @@ -1302,13 +1302,15 @@ static int igt_reset_wait(void *arg) { struct intel_gt *gt = arg; struct i915_gpu_error *global = >i915->gpu_error; - struct intel_engine_cs *engine = gt->engine[RCS0]; + struct intel_engine_cs *engine; struct i915_request *rq; unsigned int reset_count; struct hang h; long timeout; int err; + engine = intel_selftest_find_any_engine(gt); + if (!engine || !intel_engine_can_store_dword(engine)) return 0; @@ -1432,7 +1434,7 @@ static int __igt_reset_evict_vma(struct intel_gt *gt, int (*fn)(void *), unsigned int flags) { - struct intel_engine_cs *engine = gt->engine[RCS0]; + struct intel_engine_cs *engine; struct drm_i915_gem_object *obj; struct task_struct *tsk = NULL; struct i915_request *rq; @@ -1444,6 +1446,8 @@ static int __igt_reset_evict_vma(struct intel_gt *gt, if (!gt->ggtt->num_fences && flags & EXEC_OBJECT_NEEDS_FENCE) return 0; + engine = intel_selftest_find_any_engine(gt); + if (!engine || !intel_engine_can_store_dword(engine)) return 0; @@ -1819,12 +1823,14 @@ static int igt_handle_error(void *arg) { struct intel_gt *gt = arg; struct i915_gpu_error *global = >i915->gpu_error; - struct intel_engine_cs *engine = gt->engine[RCS0]; + struct intel_engine_cs *engine; struct hang h; struct i915_request *rq; struct i915_gpu_coredump *error; int err; + engine = intel_selftest_find_any_engine(gt); + /* Check that we can issue a global GPU and engine reset */ if (!intel_has_reset_engine(gt)) -- 2.37.1
[PATCH 2/6] drm/i915/guc: Fix issues with live_preempt_cancel
From: Matthew Brost Having semaphores results in different behavior when a dependent request is cancelled. In the case of semaphores the request could be on the HW and complete successfully while without the request is held in the driver and the error from the dependent request is propagated. Fix live_preempt_cancel to take this behavior into account. Also update live_preempt_cancel to use new function intel_context_ban rather than intel_context_set_banned. Signed-off-by: Matthew Brost Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/selftest_execlists.c | 16 +++- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/selftest_execlists.c b/drivers/gpu/drm/i915/gt/selftest_execlists.c index 02fc97a0ab502..015f8cd3463e2 100644 --- a/drivers/gpu/drm/i915/gt/selftest_execlists.c +++ b/drivers/gpu/drm/i915/gt/selftest_execlists.c @@ -2087,7 +2087,7 @@ static int __cancel_active0(struct live_preempt_cancel *arg) goto out; } - intel_context_set_banned(rq->context); + intel_context_ban(rq->context, rq); err = intel_engine_pulse(arg->engine); if (err) goto out; @@ -2146,7 +2146,7 @@ static int __cancel_active1(struct live_preempt_cancel *arg) if (err) goto out; - intel_context_set_banned(rq[1]->context); + intel_context_ban(rq[1]->context, rq[1]); err = intel_engine_pulse(arg->engine); if (err) goto out; @@ -2229,7 +2229,7 @@ static int __cancel_queued(struct live_preempt_cancel *arg) if (err) goto out; - intel_context_set_banned(rq[2]->context); + intel_context_ban(rq[2]->context, rq[2]); err = intel_engine_pulse(arg->engine); if (err) goto out; @@ -2244,7 +2244,13 @@ static int __cancel_queued(struct live_preempt_cancel *arg) goto out; } - if (rq[1]->fence.error != 0) { + /* +* The behavior between having semaphores and not is different. With +* semaphores the subsequent request is on the hardware and not cancelled +* while without the request is held in the driver and cancelled. +*/ + if (intel_engine_has_semaphores(rq[1]->engine) && + rq[1]->fence.error != 0) { pr_err("Normal inflight1 request did not complete\n"); err = -EINVAL; goto out; @@ -2292,7 +2298,7 @@ static int __cancel_hostile(struct live_preempt_cancel *arg) goto out; } - intel_context_set_banned(rq->context); + intel_context_ban(rq->context, rq); err = intel_engine_pulse(arg->engine); /* force reset */ if (err) goto out; -- 2.37.1
[PATCH 0/6] Random assortment of (mostly) GuC related patches
From: John Harrison Pushing a bunch of patches which had gotten forgotten about. Signed-off-by: John Harrison John Harrison (2): drm/i915/selftest: Cope with not having an RCS engine drm/i915/guc: Don't abort on CTB_UNUSED status Matthew Brost (2): drm/i915/guc: Fix issues with live_preempt_cancel drm/i915/guc: Support larger contexts on newer hardware Michał Winiarski (1): drm/i915/guc: Route semaphores to GuC for Gen12+ Rahul Kumar Singh (1): drm/i915/guc: Add selftest for a hung GuC drivers/gpu/drm/i915/gt/selftest_execlists.c | 16 +- drivers/gpu/drm/i915/gt/selftest_hangcheck.c | 12 +- .../gt/uc/abi/guc_communication_ctb_abi.h | 8 +- drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c| 10 +- drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 18 +- drivers/gpu/drm/i915/gt/uc/intel_guc_reg.h| 4 + .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 15 ++ .../drm/i915/gt/uc/selftest_guc_hangcheck.c | 159 ++ .../drm/i915/selftests/i915_live_selftests.h | 1 + 9 files changed, 227 insertions(+), 16 deletions(-) create mode 100644 drivers/gpu/drm/i915/gt/uc/selftest_guc_hangcheck.c -- 2.37.1
[PATCH 6/6] drm/i915/guc: Don't abort on CTB_UNUSED status
From: John Harrison When the KMD sends a CLIENT_RESET request to GuC (as part of the suspend sequence), GuC will mark the CTB buffer as 'UNUSED'. If the KMD then checked the CTB queue, it would see a non-zero status value and report the buffer as corrupted. Technically, no G2H messages should be received once the CLIENT_RESET has been sent. However, if a context was outstanding on an engine then it would get reset and a reset notification would be sent. So, don't actually treat UNUSED as a catastrophic error. Just flag it up as unexpected and keep going. Signed-off-by: John Harrison --- .../i915/gt/uc/abi/guc_communication_ctb_abi.h | 8 +--- drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 18 -- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_communication_ctb_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_communication_ctb_abi.h index df83c1cc7c7a6..28b8387f97b77 100644 --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_communication_ctb_abi.h +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_communication_ctb_abi.h @@ -37,6 +37,7 @@ * | | | - _`GUC_CTB_STATUS_OVERFLOW` = 1 (head/tail too large) | * | | | - _`GUC_CTB_STATUS_UNDERFLOW` = 2 (truncated message) | * | | | - _`GUC_CTB_STATUS_MISMATCH` = 4 (head/tail modified) | + * | | | - _`GUC_CTB_STATUS_UNUSED` = 8 (CTB is not in use) | * +---+---+--+ * |...| | RESERVED = MBZ | * +---+---+--+ @@ -49,9 +50,10 @@ struct guc_ct_buffer_desc { u32 tail; u32 status; #define GUC_CTB_STATUS_NO_ERROR0 -#define GUC_CTB_STATUS_OVERFLOW(1 << 0) -#define GUC_CTB_STATUS_UNDERFLOW (1 << 1) -#define GUC_CTB_STATUS_MISMATCH(1 << 2) +#define GUC_CTB_STATUS_OVERFLOWBIT(0) +#define GUC_CTB_STATUS_UNDERFLOW BIT(1) +#define GUC_CTB_STATUS_MISMATCHBIT(2) +#define GUC_CTB_STATUS_UNUSED BIT(3) u32 reserved[13]; } __packed; static_assert(sizeof(struct guc_ct_buffer_desc) == 64); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c index f01325cd1b625..11b5d4ddb19ce 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c @@ -816,8 +816,22 @@ static int ct_read(struct intel_guc_ct *ct, struct ct_incoming_msg **msg) if (unlikely(ctb->broken)) return -EPIPE; - if (unlikely(desc->status)) - goto corrupted; + if (unlikely(desc->status)) { + u32 status = desc->status; + + if (status & GUC_CTB_STATUS_UNUSED) { + /* +* Potentially valid if a CLIENT_RESET request resulted in +* contexts/engines being reset. But should never happen as +* no contexts should be active when CLIENT_RESET is sent. +*/ + CT_ERROR(ct, "Unexpected G2H after GuC has stopped!\n"); + status &= ~GUC_CTB_STATUS_UNUSED; + } + + if (status) + goto corrupted; + } GEM_BUG_ON(head > size); -- 2.37.1
[PATCH 5/6] drm/i915/guc: Support larger contexts on newer hardware
From: Matthew Brost The GuC needs a copy of a golden context for implementing watchdog resets (aka media resets). This context is larger on newer platforms. So adjust the size being allocated/copied accordingly. Signed-off-by: Matthew Brost Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c | 10 +++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c index ba7541f3ca610..74cbe8eaf5318 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c @@ -464,7 +464,11 @@ static void fill_engine_enable_masks(struct intel_gt *gt, } #define LR_HW_CONTEXT_SIZE (80 * sizeof(u32)) -#define LRC_SKIP_SIZE (LRC_PPHWSP_SZ * PAGE_SIZE + LR_HW_CONTEXT_SIZE) +#define XEHP_LR_HW_CONTEXT_SIZE (96 * sizeof(u32)) +#define LR_HW_CONTEXT_SZ(i915) (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50) ? \ + XEHP_LR_HW_CONTEXT_SIZE : \ + LR_HW_CONTEXT_SIZE) +#define LRC_SKIP_SIZE(i915) (LRC_PPHWSP_SZ * PAGE_SIZE + LR_HW_CONTEXT_SZ(i915)) static int guc_prep_golden_context(struct intel_guc *guc) { struct intel_gt *gt = guc_to_gt(guc); @@ -525,7 +529,7 @@ static int guc_prep_golden_context(struct intel_guc *guc) * on all engines). */ ads_blob_write(guc, ads.eng_state_size[guc_class], - real_size - LRC_SKIP_SIZE); + real_size - LRC_SKIP_SIZE(gt->i915)); ads_blob_write(guc, ads.golden_context_lrca[guc_class], addr_ggtt); @@ -599,7 +603,7 @@ static void guc_init_golden_context(struct intel_guc *guc) } GEM_BUG_ON(ads_blob_read(guc, ads.eng_state_size[guc_class]) != - real_size - LRC_SKIP_SIZE); + real_size - LRC_SKIP_SIZE(gt->i915)); GEM_BUG_ON(ads_blob_read(guc, ads.golden_context_lrca[guc_class]) != addr_ggtt); addr_ggtt += alloc_size; -- 2.37.1
[PATCH 1/6] drm/i915/guc: Route semaphores to GuC for Gen12+
From: Michał Winiarski In GuC submission mode, there is an option to use auto-switch out semaphores and have GuC auto-switch in a waiting context. This requires routing the semaphore interrupt to GuC. Signed-off-by: Michał Winiarski Signed-off-by: John Harrison Reviewed-by: Matthew Brost Reviewed-by: Daniele Ceraolo Spurio --- drivers/gpu/drm/i915/gt/uc/intel_guc_reg.h| 4 drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 14 ++ 2 files changed, 18 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_reg.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_reg.h index 8dc063f087eb1..a7092f711e9cd 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_reg.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_reg.h @@ -102,6 +102,10 @@ #define GUC_SEND_TRIGGER (1<<0) #define GEN11_GUC_HOST_INTERRUPT _MMIO(0x1901f0) +#define GEN12_GUC_SEM_INTR_ENABLES _MMIO(0xc71c) +#define GUC_SEM_INTR_ROUTE_TO_GUCBIT(31) +#define GUC_SEM_INTR_ENABLE_ALL (0xff) + #define GUC_NUM_DOORBELLS 256 /* format of the HW-monitored doorbell cacheline */ diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index 76916aed897ad..0b8c6450fa344 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -4191,13 +4191,27 @@ int intel_guc_submission_setup(struct intel_engine_cs *engine) void intel_guc_submission_enable(struct intel_guc *guc) { + struct intel_gt *gt = guc_to_gt(guc); + + /* Enable and route to GuC */ + if (GRAPHICS_VER(gt->i915) >= 12) + intel_uncore_write(gt->uncore, GEN12_GUC_SEM_INTR_ENABLES, + GUC_SEM_INTR_ROUTE_TO_GUC | + GUC_SEM_INTR_ENABLE_ALL); + guc_init_lrc_mapping(guc); guc_init_engine_stats(guc); } void intel_guc_submission_disable(struct intel_guc *guc) { + struct intel_gt *gt = guc_to_gt(guc); + /* Note: By the time we're here, GuC may have already been reset */ + + /* Disable and route to host */ + if (GRAPHICS_VER(gt->i915) >= 12) + intel_uncore_write(gt->uncore, GEN12_GUC_SEM_INTR_ENABLES, 0x0); } static bool __guc_submission_supported(struct intel_guc *guc) -- 2.37.1
[PATCH v4 2/2] drm: panel: Add novatek nt35596s panel driver
Novatek NT35596s is a generic DSI IC that drives command and video mode panels. Add the driver for it. Currently add support for the LCD panel from JDI connected with this IC, as found on Xiaomi Mi Mix2s phones. Changes in v4: - No change. Changes in v3: - Embed the support into existing driver (panel-novatek-nt36672a), as these two IC are similar with different initialization commands. Signed-off-by: Molly Sophia --- drivers/gpu/drm/panel/Kconfig | 7 +- .../gpu/drm/panel/panel-novatek-nt36672a.c| 246 -- 2 files changed, 234 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index 38799effd00a..ecc1b9aa6a1c 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig @@ -328,14 +328,15 @@ config DRM_PANEL_NOVATEK_NT35950 mobile phones. config DRM_PANEL_NOVATEK_NT36672A - tristate "Novatek NT36672A DSI panel" + tristate "Novatek NT36672A/NT35596S DSI panel" depends on OF depends on DRM_MIPI_DSI depends on BACKLIGHT_CLASS_DEVICE help Say Y here if you want to enable support for the panels built - around the Novatek NT36672A display controller, such as some - Tianma panels used in a few Xiaomi Poco F1 mobile phones. + around the Novatek NT36672A or NT35596S display controller, such + as some Tianma panels used in a few Xiaomi Poco F1 mobile phones + or the JDI panels used in Xiaomi Mi Mix2S mobile phones. config DRM_PANEL_NOVATEK_NT39016 tristate "Novatek NT39016 RGB/SPI panel" diff --git a/drivers/gpu/drm/panel/panel-novatek-nt36672a.c b/drivers/gpu/drm/panel/panel-novatek-nt36672a.c index 231f371901e8..fcdde538d847 100644 --- a/drivers/gpu/drm/panel/panel-novatek-nt36672a.c +++ b/drivers/gpu/drm/panel/panel-novatek-nt36672a.c @@ -3,13 +3,15 @@ * Copyright (C) 2020 Linaro Ltd * Author: Sumit Semwal * - * This driver is for the DSI interface to panels using the NT36672A display driver IC + * Copyright (C) 2022 Molly Sophia + * + * This driver is for the DSI interface to panels using the NT36672A/NT35596S display driver IC * from Novatek. * Currently supported are the Tianma FHD+ panels found in some Xiaomi phones, including - * some variants of the Poco F1 phone. + * some variants of the Poco F1 phone, and the JDI FHD+ panels found in Xiaomi Mi Mix2S phones. * - * Panels using the Novatek NT37762A IC should add appropriate configuration per-panel and - * use this driver. + * Panels using the Novatek NT37762A or NT35596S IC should add appropriate configuration + * per-panel and use this driver. */ #include @@ -123,12 +125,14 @@ static int nt36672a_panel_unprepare(struct drm_panel *panel) if (!pinfo->prepared) return 0; - /* send off cmds */ - ret = nt36672a_send_cmds(panel, pinfo->desc->off_cmds, -pinfo->desc->num_off_cmds); + if (pinfo->desc->num_off_cmds != 0) { + /* send off cmds if present */ + ret = nt36672a_send_cmds(panel, pinfo->desc->off_cmds, + pinfo->desc->num_off_cmds); - if (ret < 0) - dev_err(panel->dev, "failed to send DCS off cmds: %d\n", ret); + if (ret < 0) + dev_err(panel->dev, "failed to send DCS off cmds: %d\n", ret); + } ret = mipi_dsi_dcs_set_display_off(pinfo->link); if (ret < 0) @@ -211,13 +215,15 @@ static int nt36672a_panel_prepare(struct drm_panel *panel) goto poweroff; } - /* Send rest of the init cmds */ - err = nt36672a_send_cmds(panel, pinfo->desc->on_cmds_2, -pinfo->desc->num_on_cmds_2); + if (pinfo->desc->num_on_cmds_2 != 0) { + /* Send rest of the init cmds if present */ + err = nt36672a_send_cmds(panel, pinfo->desc->on_cmds_2, + pinfo->desc->num_on_cmds_2); - if (err < 0) { - dev_err(panel->dev, "failed to send DCS Init 2nd Code: %d\n", err); - goto poweroff; + if (err < 0) { + dev_err(panel->dev, "failed to send DCS Init 2nd Code: %d\n", err); + goto poweroff; + } } msleep(120); @@ -601,6 +607,212 @@ static const struct nt36672a_panel_desc tianma_fhd_video_panel_desc = { .num_off_cmds = ARRAY_SIZE(tianma_fhd_video_off_cmds), }; +static const struct nt36672a_panel_cmd jdi_nt35596s_video_on_cmds[] = { + { .data = { 0xff, 0x24 } }, + { .data = { 0x9d, 0x34 } }, + { .data = { 0xfb, 0x01 } }, + { .data = { 0xc4, 0x25 } }, + { .data = { 0xd1, 0x08 } }, + { .data = { 0xd2, 0x84 } }, + { .data = { 0xff, 0x26 } }, + { .data = { 0xfb, 0x01 } }, + { .data = { 0x03, 0x1c }
[PATCH v4 0/2] Add driver for Novatek NT35596S panel
These patches add support for Novatek NT35596S based JDI FHD panels, found in Xiaomi Mi Mix2S mobile phones. Changes in v4: - Correct numeric order of the items in binding. Changes in v3: - Embed the support into existing driver (panel-novatek-nt36672a), as these two IC are similar with different initialization commands. Changes in v2: - Correct items order in Makefile and improve failure handling. Molly Sophia (2): dt-bindings: display: panel: Add Novatek NT35596S panel bindings drm: panel: Add novatek nt35596s panel driver .../display/panel/novatek,nt36672a.yaml | 20 +- drivers/gpu/drm/panel/Kconfig | 7 +- .../gpu/drm/panel/panel-novatek-nt36672a.c| 246 -- 3 files changed, 247 insertions(+), 26 deletions(-) -- 2.37.1
[PATCH v4 1/2] dt-bindings: display: panel: Add Novatek NT35596S panel bindings
Add documentation for "novatek,nt35596s" panel. Changes in v4: - Correct numeric order of the items. Changes in v3: - Embed the documentation into existing one (novatek,nt36672a). Signed-off-by: Molly Sophia --- .../display/panel/novatek,nt36672a.yaml | 20 --- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/Documentation/devicetree/bindings/display/panel/novatek,nt36672a.yaml b/Documentation/devicetree/bindings/display/panel/novatek,nt36672a.yaml index 563766d283f6..d21a4a87a9d8 100644 --- a/Documentation/devicetree/bindings/display/panel/novatek,nt36672a.yaml +++ b/Documentation/devicetree/bindings/display/panel/novatek,nt36672a.yaml @@ -20,14 +20,20 @@ allOf: properties: compatible: -items: - - enum: - - tianma,fhd-video - - const: novatek,nt36672a +oneOf: + - items: + - enum: + - jdi,fhd-nt35596s + - const: novatek,nt35596s + + - items: + - enum: + - tianma,fhd-video + - const: novatek,nt36672a + description: This indicates the panel manufacturer of the panel that is - in turn using the NT36672A panel driver. This compatible string - determines how the NT36672A panel driver is configured for the indicated - panel. The novatek,nt36672a compatible shall always be provided as a fallback. + in turn using the NT36672A or the NT35596S panel driver. This compatible string + determines how the panel driver is configured for the indicated panel. reset-gpios: maxItems: 1 -- 2.37.1
[PATCH 3/7] drm/i915/guc: Add GuC <-> kernel time stamp translation information
From: John Harrison It is useful to be able to match GuC events to kernel events when looking at the GuC log. That requires being able to convert GuC timestamps to kernel time. So, when dumping error captures and/or GuC logs, include a stamp in both time zones plus the clock frequency. Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/intel_gt_regs.h| 2 ++ drivers/gpu/drm/i915/gt/uc/intel_guc.c | 19 +++ drivers/gpu/drm/i915/gt/uc/intel_guc.h | 2 ++ drivers/gpu/drm/i915/gt/uc/intel_guc_log.c | 2 ++ drivers/gpu/drm/i915/i915_gpu_error.c | 12 drivers/gpu/drm/i915/i915_gpu_error.h | 3 +++ 6 files changed, 40 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/intel_gt_regs.h b/drivers/gpu/drm/i915/gt/intel_gt_regs.h index 60d6eb5f245b7..fc7979bd91db5 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_regs.h +++ b/drivers/gpu/drm/i915/gt/intel_gt_regs.h @@ -1007,6 +1007,8 @@ #define GEN11_LSN_UNSLCVC_GAFS_HALF_CL2_MAXALLOC (1 << 9) #define GEN11_LSN_UNSLCVC_GAFS_HALF_SF_MAXALLOC (1 << 7) +#define GUCPMTIMESTAMP _MMIO(0xc3e8) + #define __GEN9_RCS0_MOCS0 0xc800 #define GEN9_GFX_MOCS(i) _MMIO(__GEN9_RCS0_MOCS0 + (i) * 4) #define __GEN9_VCS0_MOCS0 0xc900 diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c index 2706a8c650900..ab4aacc516aa4 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c @@ -389,6 +389,25 @@ void intel_guc_write_params(struct intel_guc *guc) intel_uncore_forcewake_put(uncore, FORCEWAKE_GT); } +void intel_guc_dump_time_info(struct intel_guc *guc, struct drm_printer *p) +{ + struct intel_gt *gt = guc_to_gt(guc); + intel_wakeref_t wakeref; + u32 stamp = 0; + u64 ktime; + + intel_device_info_print_runtime(RUNTIME_INFO(gt->i915), p); + + with_intel_runtime_pm(>i915->runtime_pm, wakeref) + stamp = intel_uncore_read(gt->uncore, GUCPMTIMESTAMP); + ktime = ktime_get_boottime_ns(); + + drm_printf(p, "Kernel timestamp: 0x%08llX [%llu]\n", ktime, ktime); + drm_printf(p, "GuC timestamp: 0x%08X [%u]\n", stamp, stamp); + drm_printf(p, "CS timestamp frequency: %u Hz, %u ns\n", + gt->clock_frequency, gt->clock_period_ns); +} + int intel_guc_init(struct intel_guc *guc) { struct intel_gt *gt = guc_to_gt(guc); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h index a7acffbf15d1f..804133df1ac9b 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h @@ -464,4 +464,6 @@ void intel_guc_load_status(struct intel_guc *guc, struct drm_printer *p); void intel_guc_write_barrier(struct intel_guc *guc); +void intel_guc_dump_time_info(struct intel_guc *guc, struct drm_printer *p); + #endif diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c index 991d4a02248dc..07d31ae32f765 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c @@ -764,6 +764,8 @@ int intel_guc_log_dump(struct intel_guc_log *log, struct drm_printer *p, if (!obj) return 0; + intel_guc_dump_time_info(guc, p); + map = i915_gem_object_pin_map_unlocked(obj, I915_MAP_WC); if (IS_ERR(map)) { DRM_DEBUG("Failed to pin object\n"); diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 32e92651ef7c2..addba75252343 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -678,6 +678,7 @@ static void err_print_uc(struct drm_i915_error_state_buf *m, intel_uc_fw_dump(_uc->guc_fw, ); intel_uc_fw_dump(_uc->huc_fw, ); + err_printf(m, "GuC timestamp: 0x%08x\n", error_uc->timestamp); intel_gpu_error_print_vma(m, NULL, error_uc->guc_log); } @@ -720,6 +721,8 @@ static void err_print_gt_global_nonguc(struct drm_i915_error_state_buf *m, int i; err_printf(m, "GT awake: %s\n", str_yes_no(gt->awake)); + err_printf(m, "CS timestamp frequency: %u Hz, %d ns\n", + gt->clock_frequency, gt->clock_period_ns); err_printf(m, "EIR: 0x%08x\n", gt->eir); err_printf(m, "PGTBL_ER: 0x%08x\n", gt->pgtbl_er); @@ -1675,6 +1678,13 @@ gt_record_uc(struct intel_gt_coredump *gt, */ error_uc->guc_fw.path = kstrdup(uc->guc.fw.path, ALLOW_FAIL); error_uc->huc_fw.path = kstrdup(uc->huc.fw.path, ALLOW_FAIL); + + /* +* Save the GuC log and include a timestamp reference for converting the +* log times to system times (in conjunction with the error->boottime and +* gt->clock_frequency fields saved elsewhere). +*/ + error_uc->timestamp =
[PATCH 4/7] drm/i915/guc: Record CTB info in error logs
From: John Harrison When debugging GuC communication issues, it is useful to have the CTB info available. So add the state and buffer contents to the error capture log. Also, add a sub-structure for the GuC specific error capture info as it is now becoming numerous. Signed-off-by: John Harrison --- drivers/gpu/drm/i915/i915_gpu_error.c | 59 +++ drivers/gpu/drm/i915/i915_gpu_error.h | 20 +++-- 2 files changed, 67 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index addba75252343..543ba63f958ea 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -671,6 +671,18 @@ static void err_print_pciid(struct drm_i915_error_state_buf *m, pdev->subsystem_device); } +static void err_print_guc_ctb(struct drm_i915_error_state_buf *m, + const char *name, + const struct intel_ctb_coredump *ctb) +{ + if (!ctb->size) + return; + + err_printf(m, "GuC %s CTB: raw: 0x%08X, 0x%08X/%08X, cached: 0x%08X/%08X, desc = 0x%08X, buf = 0x%08X x 0x%08X\n", + name, ctb->raw_status, ctb->raw_head, ctb->raw_tail, + ctb->head, ctb->tail, ctb->desc_offset, ctb->cmds_offset, ctb->size); +} + static void err_print_uc(struct drm_i915_error_state_buf *m, const struct intel_uc_coredump *error_uc) { @@ -678,8 +690,12 @@ static void err_print_uc(struct drm_i915_error_state_buf *m, intel_uc_fw_dump(_uc->guc_fw, ); intel_uc_fw_dump(_uc->huc_fw, ); - err_printf(m, "GuC timestamp: 0x%08x\n", error_uc->timestamp); - intel_gpu_error_print_vma(m, NULL, error_uc->guc_log); + err_printf(m, "GuC timestamp: 0x%08x\n", error_uc->guc.timestamp); + intel_gpu_error_print_vma(m, NULL, error_uc->guc.vma_log); + err_printf(m, "GuC CTB fence: %d\n", error_uc->guc.last_fence); + err_print_guc_ctb(m, "Send", error_uc->guc.ctb + 0); + err_print_guc_ctb(m, "Recv", error_uc->guc.ctb + 1); + intel_gpu_error_print_vma(m, NULL, error_uc->guc.vma_ctb); } static void err_free_sgl(struct scatterlist *sgl) @@ -854,7 +870,7 @@ static void __err_print_to_sgl(struct drm_i915_error_state_buf *m, if (error->gt) { bool print_guc_capture = false; - if (error->gt->uc && error->gt->uc->is_guc_capture) + if (error->gt->uc && error->gt->uc->guc.is_guc_capture) print_guc_capture = true; err_print_gt_display(m, error->gt); @@ -1009,7 +1025,8 @@ static void cleanup_uc(struct intel_uc_coredump *uc) { kfree(uc->guc_fw.path); kfree(uc->huc_fw.path); - i915_vma_coredump_free(uc->guc_log); + i915_vma_coredump_free(uc->guc.vma_log); + i915_vma_coredump_free(uc->guc.vma_ctb); kfree(uc); } @@ -1658,6 +1675,23 @@ gt_record_engines(struct intel_gt_coredump *gt, } } +static void gt_record_guc_ctb(struct intel_ctb_coredump *saved, + const struct intel_guc_ct_buffer *ctb, + const void *blob_ptr, struct intel_guc *guc) +{ + if (!ctb || !ctb->desc) + return; + + saved->raw_status = ctb->desc->status; + saved->raw_head = ctb->desc->head; + saved->raw_tail = ctb->desc->tail; + saved->head = ctb->head; + saved->tail = ctb->tail; + saved->size = ctb->size; + saved->desc_offset = ((void *)ctb->desc) - blob_ptr; + saved->cmds_offset = ((void *)ctb->cmds) - blob_ptr; +} + static struct intel_uc_coredump * gt_record_uc(struct intel_gt_coredump *gt, struct i915_vma_compress *compress) @@ -1684,9 +1718,16 @@ gt_record_uc(struct intel_gt_coredump *gt, * log times to system times (in conjunction with the error->boottime and * gt->clock_frequency fields saved elsewhere). */ - error_uc->timestamp = intel_uncore_read(gt->_gt->uncore, GUCPMTIMESTAMP); - error_uc->guc_log = create_vma_coredump(gt->_gt, uc->guc.log.vma, - "GuC log buffer", compress); + error_uc->guc.timestamp = intel_uncore_read(gt->_gt->uncore, GUCPMTIMESTAMP); + error_uc->guc.vma_log = create_vma_coredump(gt->_gt, uc->guc.log.vma, + "GuC log buffer", compress); + error_uc->guc.vma_ctb = create_vma_coredump(gt->_gt, uc->guc.ct.vma, + "GuC CT buffer", compress); + error_uc->guc.last_fence = uc->guc.ct.requests.last_fence; + gt_record_guc_ctb(error_uc->guc.ctb + 0, >guc.ct.ctbs.send, + uc->guc.ct.ctbs.send.desc, (struct intel_guc *)>guc); + gt_record_guc_ctb(error_uc->guc.ctb + 1, >guc.ct.ctbs.recv, +
[PATCH 6/7] drm/i915/guc: Make GuC log sizes runtime configurable
From: John Harrison The GuC log buffer sizes had to be configured statically at compile time. This can be quite troublesome when needing to get larger logs out of a released driver. So re-organise the code to allow a boot time module parameter override. Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/uc/intel_guc.c| 53 ++ .../gpu/drm/i915/gt/uc/intel_guc_capture.c| 14 +- drivers/gpu/drm/i915/gt/uc/intel_guc_log.c| 176 +- drivers/gpu/drm/i915/gt/uc/intel_guc_log.h| 42 +++-- drivers/gpu/drm/i915/i915_params.c| 12 ++ drivers/gpu/drm/i915/i915_params.h| 3 + 6 files changed, 226 insertions(+), 74 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c index ab4aacc516aa4..01f2705cb94a3 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c @@ -224,53 +224,22 @@ static u32 guc_ctl_feature_flags(struct intel_guc *guc) static u32 guc_ctl_log_params_flags(struct intel_guc *guc) { - u32 offset = intel_guc_ggtt_offset(guc, guc->log.vma) >> PAGE_SHIFT; - u32 flags; - - #if (((CRASH_BUFFER_SIZE) % SZ_1M) == 0) - #define LOG_UNIT SZ_1M - #define LOG_FLAG GUC_LOG_LOG_ALLOC_UNITS - #else - #define LOG_UNIT SZ_4K - #define LOG_FLAG 0 - #endif - - #if (((CAPTURE_BUFFER_SIZE) % SZ_1M) == 0) - #define CAPTURE_UNIT SZ_1M - #define CAPTURE_FLAG GUC_LOG_CAPTURE_ALLOC_UNITS - #else - #define CAPTURE_UNIT SZ_4K - #define CAPTURE_FLAG 0 - #endif - - BUILD_BUG_ON(!CRASH_BUFFER_SIZE); - BUILD_BUG_ON(!IS_ALIGNED(CRASH_BUFFER_SIZE, LOG_UNIT)); - BUILD_BUG_ON(!DEBUG_BUFFER_SIZE); - BUILD_BUG_ON(!IS_ALIGNED(DEBUG_BUFFER_SIZE, LOG_UNIT)); - BUILD_BUG_ON(!CAPTURE_BUFFER_SIZE); - BUILD_BUG_ON(!IS_ALIGNED(CAPTURE_BUFFER_SIZE, CAPTURE_UNIT)); - - BUILD_BUG_ON((CRASH_BUFFER_SIZE / LOG_UNIT - 1) > - (GUC_LOG_CRASH_MASK >> GUC_LOG_CRASH_SHIFT)); - BUILD_BUG_ON((DEBUG_BUFFER_SIZE / LOG_UNIT - 1) > - (GUC_LOG_DEBUG_MASK >> GUC_LOG_DEBUG_SHIFT)); - BUILD_BUG_ON((CAPTURE_BUFFER_SIZE / CAPTURE_UNIT - 1) > - (GUC_LOG_CAPTURE_MASK >> GUC_LOG_CAPTURE_SHIFT)); + struct intel_guc_log *log = >log; + u32 offset, flags; + + GEM_BUG_ON(!log->sizes_initialised); + + offset = intel_guc_ggtt_offset(guc, log->vma) >> PAGE_SHIFT; flags = GUC_LOG_VALID | GUC_LOG_NOTIFY_ON_HALF_FULL | - CAPTURE_FLAG | - LOG_FLAG | - ((CRASH_BUFFER_SIZE / LOG_UNIT - 1) << GUC_LOG_CRASH_SHIFT) | - ((DEBUG_BUFFER_SIZE / LOG_UNIT - 1) << GUC_LOG_DEBUG_SHIFT) | - ((CAPTURE_BUFFER_SIZE / CAPTURE_UNIT - 1) << GUC_LOG_CAPTURE_SHIFT) | + log->sizes[GUC_LOG_SECTIONS_DEBUG].flag | + log->sizes[GUC_LOG_SECTIONS_CAPTURE].flag | + (log->sizes[GUC_LOG_SECTIONS_CRASH].count << GUC_LOG_CRASH_SHIFT) | + (log->sizes[GUC_LOG_SECTIONS_DEBUG].count << GUC_LOG_DEBUG_SHIFT) | + (log->sizes[GUC_LOG_SECTIONS_CAPTURE].count << GUC_LOG_CAPTURE_SHIFT) | (offset << GUC_LOG_BUF_ADDR_SHIFT); - #undef LOG_UNIT - #undef LOG_FLAG - #undef CAPTURE_UNIT - #undef CAPTURE_FLAG - return flags; } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c index b54b7883320b1..d2ac53d4f3b6e 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -656,16 +656,17 @@ static void check_guc_capture_size(struct intel_guc *guc) struct drm_i915_private *i915 = guc_to_gt(guc)->i915; int min_size = guc_capture_output_min_size_est(guc); int spare_size = min_size * GUC_CAPTURE_OVERBUFFER_MULTIPLIER; + u32 buffer_size = intel_guc_log_section_size_capture(>log); if (min_size < 0) drm_warn(>drm, "Failed to calculate GuC error state capture buffer minimum size: %d!\n", min_size); - else if (min_size > CAPTURE_BUFFER_SIZE) + else if (min_size > buffer_size) drm_warn(>drm, "GuC error state capture buffer is too small: %d < %d\n", -CAPTURE_BUFFER_SIZE, min_size); - else if (spare_size > CAPTURE_BUFFER_SIZE) +buffer_size, min_size); + else if (spare_size > buffer_size) drm_notice(>drm, "GuC error state capture buffer maybe too small: %d < %d (min = %d)\n", - CAPTURE_BUFFER_SIZE, spare_size, min_size); + buffer_size, spare_size, min_size); } /* @@ -1294,7 +1295,8 @@ static void __guc_capture_process_output(struct intel_guc *guc) log_buf_state =
[PATCH 2/7] drm/i915/guc: Fix capture size warning and bump the size
From: John Harrison There was a size check to warn if the GuC error state capture buffer allocation would be too small to fit a reasonable amount of capture data for the current platform. Unfortunately, the test was done too early in the boot sequence and was actually testing 'if(-ENODEV > size)'. Move the check to be later. The check is only used to print a warning message, so it doesn't really matter how early or late it is done. Note that it is not possible to dynamically size the buffer because the allocation needs to be done before the engine information is available (at least, it would be in the intended two-phase GuC init process). Now that the check works, it is reporting size too small for newer platforms. The check includes a 3x oversample multiplier to allow for multiple error captures to be bufferd by GuC before i915 has a chance to read them out. This is less important than simply being big enough to fit the first capture. So a) bump the default size to be large enough for one capture minimum and b) make the warning only if one capture won't fit, instead use a notice for the 3x size. Note that the size estimate is a worst case scenario. Actual captures will likely be smaller. Lastly, use drm_warn istead of DRM_WARN as the former provides more infmration and the latter is deprecated. Signed-off-by: John Harrison --- .../gpu/drm/i915/gt/uc/intel_guc_capture.c| 40 ++- .../gpu/drm/i915/gt/uc/intel_guc_capture.h| 1 - drivers/gpu/drm/i915/gt/uc/intel_guc_log.c| 4 -- drivers/gpu/drm/i915/gt/uc/intel_guc_log.h| 4 +- 4 files changed, 31 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c index 75257bd20ff01..b54b7883320b1 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -600,10 +600,8 @@ intel_guc_capture_getnullheader(struct intel_guc *guc, return 0; } -#define GUC_CAPTURE_OVERBUFFER_MULTIPLIER 3 - -int -intel_guc_capture_output_min_size_est(struct intel_guc *guc) +static int +guc_capture_output_min_size_est(struct intel_guc *guc) { struct intel_gt *gt = guc_to_gt(guc); struct intel_engine_cs *engine; @@ -623,13 +621,8 @@ intel_guc_capture_output_min_size_est(struct intel_guc *guc) * For each engine instance, there would be 1 x guc_state_capture_group_t output * followed by 3 x guc_state_capture_t lists. The latter is how the register * dumps are split across different register types (where the '3' are global vs class -* vs instance). Finally, let's multiply the whole thing by 3x (just so we are -* not limited to just 1 round of data in a worst case full register dump log) -* -* NOTE: intel_guc_log that allocates the log buffer would round this size up to -* a power of two. +* vs instance). */ - for_each_engine(engine, gt, id) { worst_min_size += sizeof(struct guc_state_capture_group_header_t) + (3 * sizeof(struct guc_state_capture_header_t)); @@ -649,7 +642,30 @@ intel_guc_capture_output_min_size_est(struct intel_guc *guc) worst_min_size += (num_regs * sizeof(struct guc_mmio_reg)); - return (worst_min_size * GUC_CAPTURE_OVERBUFFER_MULTIPLIER); + return worst_min_size; +} + +/* + * Add on a 3x multiplier to allow for multiple back-to-back captures occurring + * before the i915 can read the data out and process it + */ +#define GUC_CAPTURE_OVERBUFFER_MULTIPLIER 3 + +static void check_guc_capture_size(struct intel_guc *guc) +{ + struct drm_i915_private *i915 = guc_to_gt(guc)->i915; + int min_size = guc_capture_output_min_size_est(guc); + int spare_size = min_size * GUC_CAPTURE_OVERBUFFER_MULTIPLIER; + + if (min_size < 0) + drm_warn(>drm, "Failed to calculate GuC error state capture buffer minimum size: %d!\n", +min_size); + else if (min_size > CAPTURE_BUFFER_SIZE) + drm_warn(>drm, "GuC error state capture buffer is too small: %d < %d\n", +CAPTURE_BUFFER_SIZE, min_size); + else if (spare_size > CAPTURE_BUFFER_SIZE) + drm_notice(>drm, "GuC error state capture buffer maybe too small: %d < %d (min = %d)\n", + CAPTURE_BUFFER_SIZE, spare_size, min_size); } /* @@ -1580,5 +1596,7 @@ int intel_guc_capture_init(struct intel_guc *guc) INIT_LIST_HEAD(>capture->outlist); INIT_LIST_HEAD(>capture->cachelist); + check_guc_capture_size(guc); + return 0; } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h index d3d7bd0b6db64..fbd3713c7832d 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h @@ -21,7 +21,6
[PATCH 1/7] drm/i915/guc: Add a helper for log buffer size
From: Alan Previn Add a helper to get GuC log buffer size. Signed-off-by: Alan Previn Signed-off-by: John Harrison Reviewed-by: Matthew Brost --- drivers/gpu/drm/i915/gt/uc/intel_guc_log.c | 49 -- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c index 25b2d7ce6640d..492bbf419d4df 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c @@ -15,6 +15,32 @@ static void guc_log_copy_debuglogs_for_relay(struct intel_guc_log *log); +static u32 intel_guc_log_size(struct intel_guc_log *log) +{ + /* +* GuC Log buffer Layout: +* +* NB: Ordering must follow "enum guc_log_buffer_type". +* +* +===+ 00B +* | Debug state header | +* +---+ 32B +* |Crash dump state header| +* +---+ 64B +* | Capture state header | +* +---+ 96B +* | | +* +===+ PAGE_SIZE (4KB) +* | Debug logs | +* +===+ + DEBUG_SIZE +* |Crash Dump logs| +* +===+ + CRASH_SIZE +* | Capture logs | +* +===+ + CAPTURE_SIZE +*/ + return PAGE_SIZE + CRASH_BUFFER_SIZE + DEBUG_BUFFER_SIZE + CAPTURE_BUFFER_SIZE; +} + /** * DOC: GuC firmware log * @@ -461,32 +487,11 @@ int intel_guc_log_create(struct intel_guc_log *log) GEM_BUG_ON(log->vma); - /* -* GuC Log buffer Layout -* (this ordering must follow "enum guc_log_buffer_type" definition) -* -* +===+ 00B -* | Debug state header | -* +---+ 32B -* |Crash dump state header| -* +---+ 64B -* | Capture state header | -* +---+ 96B -* | | -* +===+ PAGE_SIZE (4KB) -* | Debug logs | -* +===+ + DEBUG_SIZE -* |Crash Dump logs| -* +===+ + CRASH_SIZE -* | Capture logs | -* +===+ + CAPTURE_SIZE -*/ if (intel_guc_capture_output_min_size_est(guc) > CAPTURE_BUFFER_SIZE) DRM_WARN("GuC log buffer for state_capture maybe too small. %d < %d\n", CAPTURE_BUFFER_SIZE, intel_guc_capture_output_min_size_est(guc)); - guc_log_size = PAGE_SIZE + CRASH_BUFFER_SIZE + DEBUG_BUFFER_SIZE + - CAPTURE_BUFFER_SIZE; + guc_log_size = intel_guc_log_size(log); vma = intel_guc_allocate_vma(guc, guc_log_size); if (IS_ERR(vma)) { -- 2.37.1
[PATCH 5/7] drm/i915/guc: Use streaming loads to speed up dumping the guc log
From: Chris Wilson Use a temporary page and mempy_from_wc to reduce the time it takes to dump the guc log to debugfs. Signed-off-by: Chris Wilson Signed-off-by: John Harrison Reviewed-by: John Harrison --- drivers/gpu/drm/i915/gt/uc/intel_guc_log.c | 24 -- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c index 07d31ae32f765..4722d4b18ed19 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c @@ -750,8 +750,9 @@ int intel_guc_log_dump(struct intel_guc_log *log, struct drm_printer *p, struct intel_guc *guc = log_to_guc(log); struct intel_uc *uc = container_of(guc, struct intel_uc, guc); struct drm_i915_gem_object *obj = NULL; - u32 *map; - int i = 0; + void *map; + u32 *page; + int i, j; if (!intel_guc_is_supported(guc)) return -ENODEV; @@ -764,23 +765,34 @@ int intel_guc_log_dump(struct intel_guc_log *log, struct drm_printer *p, if (!obj) return 0; + page = (u32 *)__get_free_page(GFP_KERNEL); + if (!page) + return -ENOMEM; + intel_guc_dump_time_info(guc, p); map = i915_gem_object_pin_map_unlocked(obj, I915_MAP_WC); if (IS_ERR(map)) { DRM_DEBUG("Failed to pin object\n"); drm_puts(p, "(log data unaccessible)\n"); + free_page((unsigned long)page); return PTR_ERR(map); } - for (i = 0; i < obj->base.size / sizeof(u32); i += 4) - drm_printf(p, "0x%08x 0x%08x 0x%08x 0x%08x\n", - *(map + i), *(map + i + 1), - *(map + i + 2), *(map + i + 3)); + for (i = 0; i < obj->base.size; i += PAGE_SIZE) { + if (!i915_memcpy_from_wc(page, map + i, PAGE_SIZE)) + memcpy(page, map + i, PAGE_SIZE); + + for (j = 0; j < PAGE_SIZE / sizeof(u32); j += 4) + drm_printf(p, "0x%08x 0x%08x 0x%08x 0x%08x\n", + *(page + j + 0), *(page + j + 1), + *(page + j + 2), *(page + j + 3)); + } drm_puts(p, "\n"); i915_gem_object_unpin_map(obj); + free_page((unsigned long)page); return 0; } -- 2.37.1
Re: [PATCH] drm/amdkfd: use time_is_before_jiffies(a + b) to replace "jiffies - a > b"
在 2022年07月28日 00:04, Felix Kuehling 写道: This patch introduces a build warning for me: CC [M] drivers/gpu/drm/amd/amdgpu/../amdkfd/kfd_interrupt.o In file included from /home/fkuehlin/compute/kernel/include/linux/spinlock.h:54, from /home/fkuehlin/compute/kernel/include/linux/mmzone.h:8, from /home/fkuehlin/compute/kernel/include/linux/gfp.h:6, from /home/fkuehlin/compute/kernel/include/linux/slab.h:15, from /home/fkuehlin/compute/kernel/drivers/gpu/drm/amd/amdgpu/../amdkfd/kfd_interrupt.c:44: /home/fkuehlin/compute/kernel/drivers/gpu/drm/amd/amdgpu/../amdkfd/kfd_interrupt.c: In function ?interrupt_wq?: /home/fkuehlin/compute/kernel/include/linux/typecheck.h:12:18: warning: comparison of distinct pointer types lacks a cast 12 | (void)(&__dummy == &__dummy2); \ | ^~ /home/fkuehlin/compute/kernel/include/linux/jiffies.h:106:3: note: in expansion of macro ?typecheck? 106 | typecheck(unsigned long, b) && \ | ^ /home/fkuehlin/compute/kernel/include/linux/jiffies.h:154:35: note: in expansion of macro ?time_after? 154 | #define time_is_before_jiffies(a) time_after(jiffies, a) | ^~ /home/fkuehlin/compute/kernel/drivers/gpu/drm/amd/amdgpu/../amdkfd/kfd_interrupt.c:159:7: note: in expansion of macro ?time_is_before_jiffies? 159 | if (time_is_before_jiffies(start_jiffies + HZ)) { | ^~ I think you need to change the the definition of start_jiffies to be unsigned long. Do you want to submit a v2 of your patch? Yes, I will submit v2 patch later. That said, I think the existing code was fine, though the type-mismatch highlighted by your patch is a bit iffy. And if the timer wrap changes in the future you won't have to alter your driver code. So I think it's better. Regards, Felix Am 2022-07-26 um 22:59 schrieb Yu Zhe: time_is_before_jiffies deals with timer wrapping correctly. Signed-off-by: Yu Zhe --- drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c b/drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c index a9466d154395..6397926e059c 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c @@ -156,7 +156,7 @@ static void interrupt_wq(struct work_struct *work) while (dequeue_ih_ring_entry(dev, ih_ring_entry)) { dev->device_info.event_interrupt_class->interrupt_wq(dev, ih_ring_entry); -if (jiffies - start_jiffies > HZ) { +if (time_is_before_jiffies(start_jiffies + HZ)) { /* If we spent more than a second processing signals, * reschedule the worker to avoid soft-lockup warnings */
[PATCH 7/7] drm/i915/guc: Reduce spam from error capture
From: John Harrison Some debug code got left in when the GuC based register save for error capture was added. Remove that. Signed-off-by: John Harrison --- .../gpu/drm/i915/gt/uc/intel_guc_capture.c| 67 --- 1 file changed, 28 insertions(+), 39 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c index d2ac53d4f3b6e..8f11651460131 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -1383,33 +1383,22 @@ guc_capture_reg_to_str(const struct intel_guc *guc, u32 owner, u32 type, return NULL; } -#ifdef CONFIG_DRM_I915_DEBUG_GUC -#define __out(a, ...) \ - do { \ - drm_warn((&(a)->i915->drm), __VA_ARGS__); \ - i915_error_printf((a), __VA_ARGS__); \ - } while (0) -#else -#define __out(a, ...) \ - i915_error_printf(a, __VA_ARGS__) -#endif - #define GCAP_PRINT_INTEL_ENG_INFO(ebuf, eng) \ do { \ - __out(ebuf, "i915-Eng-Name: %s command stream\n", \ - (eng)->name); \ - __out(ebuf, "i915-Eng-Inst-Class: 0x%02x\n", (eng)->class); \ - __out(ebuf, "i915-Eng-Inst-Id: 0x%02x\n", (eng)->instance); \ - __out(ebuf, "i915-Eng-LogicalMask: 0x%08x\n", \ - (eng)->logical_mask); \ + i915_error_printf(ebuf, "i915-Eng-Name: %s command stream\n", \ + (eng)->name); \ + i915_error_printf(ebuf, "i915-Eng-Inst-Class: 0x%02x\n", (eng)->class); \ + i915_error_printf(ebuf, "i915-Eng-Inst-Id: 0x%02x\n", (eng)->instance); \ + i915_error_printf(ebuf, "i915-Eng-LogicalMask: 0x%08x\n", \ + (eng)->logical_mask); \ } while (0) #define GCAP_PRINT_GUC_INST_INFO(ebuf, node) \ do { \ - __out(ebuf, "GuC-Engine-Inst-Id: 0x%08x\n", \ - (node)->eng_inst); \ - __out(ebuf, "GuC-Context-Id: 0x%08x\n", (node)->guc_id); \ - __out(ebuf, "LRCA: 0x%08x\n", (node)->lrca); \ + i915_error_printf(ebuf, "GuC-Engine-Inst-Id: 0x%08x\n", \ + (node)->eng_inst); \ + i915_error_printf(ebuf, "GuC-Context-Id: 0x%08x\n", (node)->guc_id); \ + i915_error_printf(ebuf, "LRCA: 0x%08x\n", (node)->lrca); \ } while (0) int intel_guc_capture_print_engine_node(struct drm_i915_error_state_buf *ebuf, @@ -1441,57 +1430,57 @@ int intel_guc_capture_print_engine_node(struct drm_i915_error_state_buf *ebuf, guc = >engine->gt->uc.guc; - __out(ebuf, "global --- GuC Error Capture on %s command stream:\n", - ee->engine->name); + i915_error_printf(ebuf, "global --- GuC Error Capture on %s command stream:\n", + ee->engine->name); node = ee->guc_capture_node; if (!node) { - __out(ebuf, " No matching ee-node\n"); + i915_error_printf(ebuf, " No matching ee-node\n"); return 0; } - __out(ebuf, "Coverage: %s\n", grptype[node->is_partial]); + i915_error_printf(ebuf, "Coverage: %s\n", grptype[node->is_partial]); for (i = GUC_CAPTURE_LIST_TYPE_GLOBAL; i < GUC_CAPTURE_LIST_TYPE_MAX; ++i) { - __out(ebuf, " RegListType: %s\n", - datatype[i % GUC_CAPTURE_LIST_TYPE_MAX]); - __out(ebuf, "Owner-Id: %d\n", node->reginfo[i].vfid); + i915_error_printf(ebuf, " RegListType: %s\n", + datatype[i % GUC_CAPTURE_LIST_TYPE_MAX]); + i915_error_printf(ebuf, "Owner-Id: %d\n", node->reginfo[i].vfid); switch (i) { case GUC_CAPTURE_LIST_TYPE_GLOBAL: default: break; case GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS: - __out(ebuf, "GuC-Eng-Class: %d\n", node->eng_class); - __out(ebuf, "i915-Eng-Class: %d\n", - guc_class_to_engine_class(node->eng_class)); + i915_error_printf(ebuf, "GuC-Eng-Class: %d\n", node->eng_class); + i915_error_printf(ebuf, "i915-Eng-Class: %d\n", + guc_class_to_engine_class(node->eng_class)); break; case GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE: eng = intel_guc_lookup_engine(guc, node->eng_class, node->eng_inst); if (eng) GCAP_PRINT_INTEL_ENG_INFO(ebuf, eng); else - __out(ebuf, "i915-Eng-Lookup Fail!\n"); +
[PATCH 0/7] Fixes and improvements to GuC logging and error capture
From: John Harrison Fix bugs and improve the usability/effectiveness of GuC logging and GuC related error captures. Signed-off-by: John Harrison Alan Previn (1): drm/i915/guc: Add a helper for log buffer size Chris Wilson (1): drm/i915/guc: Use streaming loads to speed up dumping the guc log John Harrison (5): drm/i915/guc: Fix capture size warning and bump the size drm/i915/guc: Add GuC <-> kernel time stamp translation information drm/i915/guc: Record CTB info in error logs drm/i915/guc: Make GuC log sizes runtime configurable drm/i915/guc: Reduce spam from error capture drivers/gpu/drm/i915/gt/intel_gt_regs.h | 2 + drivers/gpu/drm/i915/gt/uc/intel_guc.c| 72 +++-- drivers/gpu/drm/i915/gt/uc/intel_guc.h| 2 + .../gpu/drm/i915/gt/uc/intel_guc_capture.c| 113 .../gpu/drm/i915/gt/uc/intel_guc_capture.h| 1 - drivers/gpu/drm/i915/gt/uc/intel_guc_log.c| 253 +++--- drivers/gpu/drm/i915/gt/uc/intel_guc_log.h| 42 +-- drivers/gpu/drm/i915/i915_gpu_error.c | 67 - drivers/gpu/drm/i915/i915_gpu_error.h | 21 +- drivers/gpu/drm/i915/i915_params.c| 12 + drivers/gpu/drm/i915/i915_params.h| 3 + 11 files changed, 427 insertions(+), 161 deletions(-) -- 2.37.1
Re: [PATCH v3 1/2] dt-bindings: display: panel: Add Novatek NT35596S panel bindings
Thanks! I'll handle that and send the new patches later. Best regards, Molly On Wed, Jul 27, 2022 at 6:24 PM Krzysztof Kozlowski wrote: > > On 26/07/2022 12:15, Molly Sophia wrote: > > Add documentation for "novatek,nt35596s" panel. > > > > Changes in v3: > > - Embed the documentation into existing one (novatek,nt36672a). > > > > Signed-off-by: Molly Sophia > > --- > > .../display/panel/novatek,nt36672a.yaml | 20 --- > > 1 file changed, 13 insertions(+), 7 deletions(-) > > > > diff --git > > a/Documentation/devicetree/bindings/display/panel/novatek,nt36672a.yaml > > b/Documentation/devicetree/bindings/display/panel/novatek,nt36672a.yaml > > index 563766d283f6..560fb66d0e5a 100644 > > --- a/Documentation/devicetree/bindings/display/panel/novatek,nt36672a.yaml > > +++ b/Documentation/devicetree/bindings/display/panel/novatek,nt36672a.yaml > > @@ -20,14 +20,20 @@ allOf: > > > > properties: > >compatible: > > -items: > > - - enum: > > - - tianma,fhd-video > > - - const: novatek,nt36672a > > +oneOf: > > + - items: > > + - enum: > > + - tianma,fhd-video > > + - const: novatek,nt36672a > > + > > + - items: > > + - enum: > > + - jdi,fhd-nt35596s > > + - const: novatek,nt35596s > > This entire entry should be rather before nt36672a judging by numbers: > > +oneOf: > + - items: > + - enum: > + - jdi,fhd-nt35596s > + - const: novatek,nt35596s > + > + - items: > + - enum: > + - tianma,fhd-video > + - const: novatek,nt36672a > > > Best regards, > Krzysztof
Re: [PATCH] drm/i915/guc: Don't send policy update for child contexts.
On 7/27/2022 18:50, Ceraolo Spurio, Daniele wrote: On 7/27/2022 6:44 PM, John Harrison wrote: On 7/27/2022 17:33, Daniele Ceraolo Spurio wrote: The GuC FW applies the parent context policy to all the children, so individual updates to the children are not supported and we should not send them. Note that sending the message did not have any functional consequences, because the GuC just drops it and logs an error; since we were trying to set the child policy to match the parent anyway the message being dropped was not a problem. Signed-off-by: Daniele Ceraolo Spurio Cc: John Harrison Needs a Fixes tag for the original v70 update patch? I don't think so. I added the explanation about it not being a functional issue to make it clear that everything still works as expected without this patch, just with a bit of extra noise in the GuC logs. If you think it is still worth applying to older kernels I'll add the tag in. Daniele Hmm. It is strictly speaking a bug fix. But yes, the only impact is extra H2G traffic on context registration and in the GuC log. So maybe not worth worrying about. Reviewed-by: John Harrison John. --- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 26 +-- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index 76916aed897a..5e31e2540297 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -2420,7 +2420,6 @@ static int guc_context_policy_init_v70(struct intel_context *ce, bool loop) struct context_policy policy; u32 execution_quantum; u32 preemption_timeout; - bool missing = false; unsigned long flags; int ret; @@ -2438,32 +2437,9 @@ static int guc_context_policy_init_v70(struct intel_context *ce, bool loop) __guc_context_policy_add_preempt_to_idle(, 1); ret = __guc_context_set_context_policies(guc, , loop); - missing = ret != 0; - - if (!missing && intel_context_is_parent(ce)) { - struct intel_context *child; - - for_each_child(ce, child) { - __guc_context_policy_start_klv(, child->guc_id.id); - - if (engine->flags & I915_ENGINE_WANT_FORCED_PREEMPTION) - __guc_context_policy_add_preempt_to_idle(, 1); - - child->guc_state.prio = ce->guc_state.prio; - __guc_context_policy_add_priority(, ce->guc_state.prio); - __guc_context_policy_add_execution_quantum(, execution_quantum); - __guc_context_policy_add_preemption_timeout(, preemption_timeout); - - ret = __guc_context_set_context_policies(guc, , loop); - if (ret) { - missing = true; - break; - } - } - } spin_lock_irqsave(>guc_state.lock, flags); - if (missing) + if (ret != 0) set_context_policy_required(ce); else clr_context_policy_required(ce);
Re: [PATCH] drm/i915/guc: Don't send policy update for child contexts.
On 7/27/2022 6:44 PM, John Harrison wrote: On 7/27/2022 17:33, Daniele Ceraolo Spurio wrote: The GuC FW applies the parent context policy to all the children, so individual updates to the children are not supported and we should not send them. Note that sending the message did not have any functional consequences, because the GuC just drops it and logs an error; since we were trying to set the child policy to match the parent anyway the message being dropped was not a problem. Signed-off-by: Daniele Ceraolo Spurio Cc: John Harrison Needs a Fixes tag for the original v70 update patch? I don't think so. I added the explanation about it not being a functional issue to make it clear that everything still works as expected without this patch, just with a bit of extra noise in the GuC logs. If you think it is still worth applying to older kernels I'll add the tag in. Daniele John. --- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 26 +-- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index 76916aed897a..5e31e2540297 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -2420,7 +2420,6 @@ static int guc_context_policy_init_v70(struct intel_context *ce, bool loop) struct context_policy policy; u32 execution_quantum; u32 preemption_timeout; - bool missing = false; unsigned long flags; int ret; @@ -2438,32 +2437,9 @@ static int guc_context_policy_init_v70(struct intel_context *ce, bool loop) __guc_context_policy_add_preempt_to_idle(, 1); ret = __guc_context_set_context_policies(guc, , loop); - missing = ret != 0; - - if (!missing && intel_context_is_parent(ce)) { - struct intel_context *child; - - for_each_child(ce, child) { - __guc_context_policy_start_klv(, child->guc_id.id); - - if (engine->flags & I915_ENGINE_WANT_FORCED_PREEMPTION) - __guc_context_policy_add_preempt_to_idle(, 1); - - child->guc_state.prio = ce->guc_state.prio; - __guc_context_policy_add_priority(, ce->guc_state.prio); - __guc_context_policy_add_execution_quantum(, execution_quantum); - __guc_context_policy_add_preemption_timeout(, preemption_timeout); - - ret = __guc_context_set_context_policies(guc, , loop); - if (ret) { - missing = true; - break; - } - } - } spin_lock_irqsave(>guc_state.lock, flags); - if (missing) + if (ret != 0) set_context_policy_required(ce); else clr_context_policy_required(ce);
Re: [PATCH] drm/i915/guc: Don't send policy update for child contexts.
On 7/27/2022 17:33, Daniele Ceraolo Spurio wrote: The GuC FW applies the parent context policy to all the children, so individual updates to the children are not supported and we should not send them. Note that sending the message did not have any functional consequences, because the GuC just drops it and logs an error; since we were trying to set the child policy to match the parent anyway the message being dropped was not a problem. Signed-off-by: Daniele Ceraolo Spurio Cc: John Harrison Needs a Fixes tag for the original v70 update patch? John. --- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 26 +-- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index 76916aed897a..5e31e2540297 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -2420,7 +2420,6 @@ static int guc_context_policy_init_v70(struct intel_context *ce, bool loop) struct context_policy policy; u32 execution_quantum; u32 preemption_timeout; - bool missing = false; unsigned long flags; int ret; @@ -2438,32 +2437,9 @@ static int guc_context_policy_init_v70(struct intel_context *ce, bool loop) __guc_context_policy_add_preempt_to_idle(, 1); ret = __guc_context_set_context_policies(guc, , loop); - missing = ret != 0; - - if (!missing && intel_context_is_parent(ce)) { - struct intel_context *child; - - for_each_child(ce, child) { - __guc_context_policy_start_klv(, child->guc_id.id); - - if (engine->flags & I915_ENGINE_WANT_FORCED_PREEMPTION) - __guc_context_policy_add_preempt_to_idle(, 1); - - child->guc_state.prio = ce->guc_state.prio; - __guc_context_policy_add_priority(, ce->guc_state.prio); - __guc_context_policy_add_execution_quantum(, execution_quantum); - __guc_context_policy_add_preemption_timeout(, preemption_timeout); - - ret = __guc_context_set_context_policies(guc, , loop); - if (ret) { - missing = true; - break; - } - } - } spin_lock_irqsave(>guc_state.lock, flags); - if (missing) + if (ret != 0) set_context_policy_required(ce); else clr_context_policy_required(ce);
[PATCH v3] gpu/drm/bridge/cadence: avoid flush_scheduled_work() usage
Like commit c4f135d643823a86 ("workqueue: Wrap flush_workqueue() using a macro") says, flush_scheduled_work() is dangerous and will be forbidden. We are on the way for removing all flush_scheduled_work() callers from the kernel, and this patch is for removing flush_scheduled_work() call from cadence driver. Since cdns-mhdp8546 driver uses 4 works mhdp->modeset_retry_work mhdp->hpd_work mhdp->hdcp.check_work mhdp->hdcp.prop_work I assume that flush_scheduled_work() in cdns_mhdp_remove() needs to wait for only these 4 works. Since mhdp->modeset_retry_work already uses cancel_work_sync(), I assume that flush_scheduled_work() needs to wait for only 3 works. But I came to wonder whether mhdp->hdcp.check_work should be flushed or cancelled. While flush_scheduled_work() waits for completion of works which were already queued to system_wq, mhdp->hdcp.check_work is a delayed work. That is, this work won't be queued to system_wq unless timeout expires. Current code will wait for mhdp->hdcp.check_work only if timeout already expired. If timeout is not expired yet, flush_scheduled_work() will fail to cancel mhdp->hdcp.check_work, and cdns_mhdp_hdcp_check_work() which is triggered by mhdp->hdcp.check_work will schedule hdcp->check_work, which is too late for flush_scheduled_work() to wait for completion of cdns_mhdp_hdcp_prop_work(). But since I couldn't get comments on how do we want to handle this race window [1], this patch chose "do nothing" for mhdp->hdcp.check_work and mhdp->hdcp.prop_work. That is, I assume that flush_scheduled_work() in cdns_mhdp_remove() needs to wait for only mhdp->hpd_work work. Link: https://lkml.kernel.org/r/943273cb-c2ec-24e3-5edb-64eacc6e2...@i-love.sakura.ne.jp [1] Signed-off-by: Tetsuo Handa --- drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c index ab63e7b11944..31442a922502 100644 --- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c +++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c @@ -2605,7 +2605,8 @@ static int cdns_mhdp_remove(struct platform_device *pdev) pm_runtime_disable(>dev); cancel_work_sync(>modeset_retry_work); - flush_scheduled_work(); + flush_work(>hpd_work); + /* Ignoring mhdp->hdcp.check_work and mhdp->hdcp.prop_work here. */ clk_disable_unprepare(mhdp->clk); -- 2.18.4
[PATCH] drm/i915/guc: Don't send policy update for child contexts.
The GuC FW applies the parent context policy to all the children, so individual updates to the children are not supported and we should not send them. Note that sending the message did not have any functional consequences, because the GuC just drops it and logs an error; since we were trying to set the child policy to match the parent anyway the message being dropped was not a problem. Signed-off-by: Daniele Ceraolo Spurio Cc: John Harrison --- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 26 +-- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index 76916aed897a..5e31e2540297 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -2420,7 +2420,6 @@ static int guc_context_policy_init_v70(struct intel_context *ce, bool loop) struct context_policy policy; u32 execution_quantum; u32 preemption_timeout; - bool missing = false; unsigned long flags; int ret; @@ -2438,32 +2437,9 @@ static int guc_context_policy_init_v70(struct intel_context *ce, bool loop) __guc_context_policy_add_preempt_to_idle(, 1); ret = __guc_context_set_context_policies(guc, , loop); - missing = ret != 0; - - if (!missing && intel_context_is_parent(ce)) { - struct intel_context *child; - - for_each_child(ce, child) { - __guc_context_policy_start_klv(, child->guc_id.id); - - if (engine->flags & I915_ENGINE_WANT_FORCED_PREEMPTION) - __guc_context_policy_add_preempt_to_idle(, 1); - - child->guc_state.prio = ce->guc_state.prio; - __guc_context_policy_add_priority(, ce->guc_state.prio); - __guc_context_policy_add_execution_quantum(, execution_quantum); - __guc_context_policy_add_preemption_timeout(, preemption_timeout); - - ret = __guc_context_set_context_policies(guc, , loop); - if (ret) { - missing = true; - break; - } - } - } spin_lock_irqsave(>guc_state.lock, flags); - if (missing) + if (ret != 0) set_context_policy_required(ce); else clr_context_policy_required(ce); -- 2.25.1
Re: [PATCH v2 0/7] drm/msm/dsi regulator improvements
On Tue, Jul 26, 2022 at 10:38:17AM -0700, Douglas Anderson wrote: > * After that I have patches that add to the regulator API and then > show a usage of those in the DSI driver. I'd expect that the two > regulator patches could land in the regulator tree. The DSI patches > would need to wait until the new regulator changes are available. The following changes since commit f2906aa863381afb0015a9eb7fefad885d4e5a56: Linux 5.19-rc1 (2022-06-05 17:18:54 -0700) are available in the Git repository at: https://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git tags/regulator-load-bulk-api for you to fetch changes up to 1de452a0edda26f1483d1d934f692eab13ba669a: regulator: core: Allow drivers to define their init data as const (2022-07-27 13:47:30 +0100) regulator: Consumer load management improvements The main goal of this series is to make a small dent in cleaning up the way we deal with regulator loads. The idea is to add some extra functionality to the regulator "bulk" API so that consumers can specify the load using that. Douglas Anderson (2): regulator: core: Allow specifying an initial load w/ the bulk API regulator: core: Allow drivers to define their init data as const drivers/regulator/core.c | 20 drivers/regulator/devres.c | 28 include/linux/regulator/consumer.h | 16 3 files changed, 52 insertions(+), 12 deletions(-) signature.asc Description: PGP signature
RE: [PATCH] drm/i915/ttm: don't leak the ccs state
> -Original Message- > From: Auld, Matthew > Sent: Wednesday, July 27, 2022 10:14 PM > To: intel-...@lists.freedesktop.org > Cc: dri-devel@lists.freedesktop.org; Thomas Hellström > ; C, > Ramalingam > Subject: [PATCH] drm/i915/ttm: don't leak the ccs state > > The kernel only manages the ccs state with lmem-only objects, however the > kernel should still take > care not to leak the CCS state from the previous user. > > Fixes: 48760ffe923a ("drm/i915/gt: Clear compress metadata for Flat-ccs > objects") > Signed-off-by: Matthew Auld > Cc: Thomas Hellström > Cc: Ramalingam C > --- > drivers/gpu/drm/i915/gt/intel_migrate.c | 23 ++- > 1 file changed, 22 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/i915/gt/intel_migrate.c > b/drivers/gpu/drm/i915/gt/intel_migrate.c > index a69b244f14d0..9a0814422ba4 100644 > --- a/drivers/gpu/drm/i915/gt/intel_migrate.c > +++ b/drivers/gpu/drm/i915/gt/intel_migrate.c > @@ -708,7 +708,7 @@ intel_context_migrate_copy(struct intel_context *ce, > u8 src_access, dst_access; > struct i915_request *rq; > int src_sz, dst_sz; > - bool ccs_is_src; > + bool ccs_is_src, overwrite_ccs; > int err; > > GEM_BUG_ON(ce->vm != ce->engine->gt->migrate.context->vm); > @@ -749,6 +749,8 @@ intel_context_migrate_copy(struct intel_context *ce, > get_ccs_sg_sgt(_ccs, bytes_to_cpy); > } > > + overwrite_ccs = HAS_FLAT_CCS(i915) && !ccs_bytes_to_cpy && > +dst_is_lmem; > + > src_offset = 0; > dst_offset = CHUNK_SZ; > if (HAS_64K_PAGES(ce->engine->i915)) { @@ -852,6 +854,25 @@ > intel_context_migrate_copy(struct intel_context *ce, > if (err) > goto out_rq; > ccs_bytes_to_cpy -= ccs_sz; > + } else if (overwrite_ccs) { > + err = rq->engine->emit_flush(rq, EMIT_INVALIDATE); > + if (err) > + goto out_rq; > + > + /* > + * While we can't always restore/manage the CCS state, > + * we still need to ensure we don't leak the CCS state > + * from the previous user, so make sure we overwrite it > + * with something. > + */ > + err = emit_copy_ccs(rq, dst_offset, INDIRECT_ACCESS, > + dst_offset, DIRECT_ACCESS, len); > + if (err) > + goto out_rq; > + > + err = rq->engine->emit_flush(rq, EMIT_INVALIDATE); > + if (err) > + goto out_rq; The change is looking good to the purpose. But shouldn't this be the part of lmem allocation itself? Ram. > } > > /* Arbitration is re-enabled between requests. */ > -- > 2.37.1
[PATCH] drm/amdgpu: Fix stub fence refcount underflow
Don't drop the stub fence reference after installing it as a replacement for the eviction fence. dma_resv_replace_fences doesn't take another reference to the fence, so it takes ownership of the reference passed in by us. Fixes: 548e7432dc2d ("dma-buf: add dma_resv_replace_fences v2") CC: Christian König Signed-off-by: Felix Kuehling --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index 87a3a3ae9448..a6c7dcd8c345 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -294,7 +294,6 @@ static int amdgpu_amdkfd_remove_eviction_fence(struct amdgpu_bo *bo, replacement = dma_fence_get_stub(); dma_resv_replace_fences(bo->tbo.base.resv, ef->base.context, replacement, DMA_RESV_USAGE_READ); - dma_fence_put(replacement); return 0; } -- 2.32.0
Re: (subset) [PATCH v2 0/7] drm/msm/dsi regulator improvements
On Tue, 26 Jul 2022 10:38:17 -0700, Douglas Anderson wrote: > The main goal of this series is to make a small dent in cleaning up > the way we deal with regulator loads. The idea is to add some extra > functionality to the regulator "bulk" API so that consumers can > specify the load using that. Though I didn't convert everyone over, I > include patches in this series that show how the Qualcomm DSI driver > is improved by this. > > [...] Applied to https://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git for-next Thanks! [4/7] regulator: core: Allow specifying an initial load w/ the bulk API commit: 6eabfc018e8d1033e7fc1efce30a872e2dccb537 [6/7] regulator: core: Allow drivers to define their init data as const commit: 1de452a0edda26f1483d1d934f692eab13ba669a All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted. You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed. If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced. Please add any relevant lists and maintainers to the CCs when replying to this mail. Thanks, Mark
Re: [PATCH] mm: Fix a null ptr deref with CONFIG_DEBUG_VM enabled in wp_page_reuse
On Wed, 2022-07-27 at 20:24 +0100, Matthew Wilcox wrote: > On Wed, Jul 27, 2022 at 03:14:07PM -0400, Zack Rusin wrote: > > From: Zack Rusin > > > > Write page faults on last references might not have a valid page anymore. > > wp_page_reuse has always dealt with that scenario by making > > sure the page isn't null (or the reference was shared) before doing > > anything with it. Recently added checks in VM_BUG_ON (enabled by the > > CONFIG_DEBUG_VM option) use PageAnon helpers which assume the passed > > page is never null, before making sure there is a valid page to work > > with. > > > > Move the VM_BUG_ON, which unconditionally uses the page, after the > > code that checks that we have a valid one. > > Message-ID: > Ah, great, thanks. z
Re: [PATCH] mm: Fix a null ptr deref with CONFIG_DEBUG_VM enabled in wp_page_reuse
On Wed, Jul 27, 2022 at 03:14:07PM -0400, Zack Rusin wrote: > From: Zack Rusin > > Write page faults on last references might not have a valid page anymore. > wp_page_reuse has always dealt with that scenario by making > sure the page isn't null (or the reference was shared) before doing > anything with it. Recently added checks in VM_BUG_ON (enabled by the > CONFIG_DEBUG_VM option) use PageAnon helpers which assume the passed > page is never null, before making sure there is a valid page to work > with. > > Move the VM_BUG_ON, which unconditionally uses the page, after the > code that checks that we have a valid one. Message-ID:
[PATCH] mm: Fix a null ptr deref with CONFIG_DEBUG_VM enabled in wp_page_reuse
From: Zack Rusin Write page faults on last references might not have a valid page anymore. wp_page_reuse has always dealt with that scenario by making sure the page isn't null (or the reference was shared) before doing anything with it. Recently added checks in VM_BUG_ON (enabled by the CONFIG_DEBUG_VM option) use PageAnon helpers which assume the passed page is never null, before making sure there is a valid page to work with. Move the VM_BUG_ON, which unconditionally uses the page, after the code that checks that we have a valid one. Fixes a kernel oops, which is easy to reproduce with 3D apps on arm64 and x86 on kernels with CONFIG_DEBUG_VM set: Unable to handle kernel paging request at virtual address dfff8001 KASAN: null-ptr-deref in range [0x0008-0x000f] Mem abort info: ESR = 0x9604 EC = 0x25: DABT (current EL), IL = 32 bits SET = 0, FnV = 0 EA = 0, S1PTW = 0 FSC = 0x04: level 0 translation fault Data abort info: ISV = 0, ISS = 0x0004 CM = 0, WnR = 0 [dfff8001] address between user and kernel address ranges Internal error: Oops: 9604 [#1] SMP CPU: 0 PID: 2396 Comm: Xwayland Tainted: G U5.19.0-rc2-vmwgfx #28 Hardware name: VMware, Inc. VMware20,1/VBSA, BIOS VMW201.00V.20138482.BA64.2207201941 07/20/2022 pstate: 1045 (nzcV daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : _compound_head+0x24/0xd0 lr : wp_page_reuse+0x8c/0x544 sp : 800013637aa0 x29: 800013637aa0 x28: 2a28b730 x27: 800013637cc8 x26: x25: 800013637d00 x24: 0c742168 x23: 126c6fa0 x22: 13ce59a0 x21: 2a28b730 x20: x19: x18: x17: x16: x15: x14: 126c6f22 x13: 65676170206c6c75 x12: 600019dc772f x11: 1fffe00019dc772e x10: 600019dc772e x9 : 885b1a78 x8 : cee3b977 x7 : 0001 x6 : 600019dc772e x5 : cee3b970 x4 : 600019dc772f x3 : 126c6f99 x2 : 0001 x1 : dfff8000 x0 : 0008 Call trace: _compound_head+0x24/0xd0 wp_page_reuse+0x8c/0x544 finish_mkwrite_fault+0x1a0/0x274 do_wp_page+0x6cc/0x1000 __handle_mm_fault+0xdc8/0x2620 handle_mm_fault+0x21c/0x530 do_page_fault+0x250/0xa40 do_mem_abort+0x78/0x1b4 el0_da+0x80/0x1c0 el0t_64_sync_handler+0xf8/0x140 el0t_64_sync+0x1a0/0x1a4 Code: aa0003f3 91002000 f2fbffe1 d343fc02 (38e16841) ---[ end trace ]--- Fixes: 6c287605fd56 ("mm: remember exclusively mapped anonymous pages with PG_anon_exclusive") Signed-off-by: Zack Rusin Cc: David Hildenbrand Cc: Vlastimil Babka Cc: Andrea Arcangeli Cc: Christoph Hellwig Cc: David Rientjes Cc: Don Dutile Cc: Hugh Dickins Cc: Jan Kara Cc: Jann Horn Cc: Jason Gunthorpe Cc: John Hubbard Cc: Khalid Aziz Cc: "Kirill A. Shutemov" Cc: Liang Zhang Cc: "Matthew Wilcox (Oracle)" Cc: Michal Hocko Cc: Mike Kravetz Cc: Mike Rapoport Cc: Nadav Amit Cc: Oded Gabbay Cc: Oleg Nesterov Cc: Pedro Demarchi Gomes Cc: Peter Xu Cc: Rik van Riel Cc: Roman Gushchin Cc: Shakeel Butt Cc: Yang Shi Cc: Andrew Morton Cc: Muchun Song Cc: Minchan Kim Cc: David Howells Cc: Miaohe Lin Cc: NeilBrown Cc: Suren Baghdasaryan Cc: Hongchen Zhang Cc: linux...@kvack.org --- mm/memory.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mm/memory.c b/mm/memory.c index 7a089145cad4..3e28c652cf60 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -3043,15 +3043,16 @@ static inline void wp_page_reuse(struct vm_fault *vmf) pte_t entry; VM_BUG_ON(!(vmf->flags & FAULT_FLAG_WRITE)); - VM_BUG_ON(PageAnon(page) && !PageAnonExclusive(page)); /* * Clear the pages cpupid information as the existing * information potentially belongs to a now completely * unrelated process. */ - if (page) + if (page) { + VM_BUG_ON(PageAnon(page) && !PageAnonExclusive(page)); page_cpupid_xchg_last(page, (1 << LAST_CPUPID_SHIFT) - 1); + } flush_cache_page(vma, vmf->address, pte_pfn(vmf->orig_pte)); entry = pte_mkyoung(vmf->orig_pte); -- 2.34.1
Re: [PATCH] dt-bindings: display: use spi-peripheral-props.yaml
Hi Krzysztof, On Wed, Jul 27, 2022 at 06:43:12PM +0200, Krzysztof Kozlowski wrote: > Instead of listing directly properties typical for SPI peripherals, > reference the spi-peripheral-props.yaml schema. This allows using all > properties typical for SPI-connected devices, even these which device > bindings author did not tried yet. > > Remove the spi-* properties which now come via spi-peripheral-props.yaml > schema, except for the cases when device schema adds some constraints > like maximum frequency. > > While changing additionalProperties->unevaluatedProperties, put it in > typical place, just before example DTS. > > The sitronix,st7735r references also panel-common.yaml and lists > explicitly allowed properties, thus here reference only > spi-peripheral-props.yaml for purpose of documenting the SPI slave > device and bringing spi-max-frequency type validation. > > Signed-off-by: Krzysztof Kozlowski Acked-by: Sam Ravnborg I assume this will be added to the same tree as the SPI CPHA and CPOL patch. Sam
[PATCH] drm/i915/ttm: don't leak the ccs state
The kernel only manages the ccs state with lmem-only objects, however the kernel should still take care not to leak the CCS state from the previous user. Fixes: 48760ffe923a ("drm/i915/gt: Clear compress metadata for Flat-ccs objects") Signed-off-by: Matthew Auld Cc: Thomas Hellström Cc: Ramalingam C --- drivers/gpu/drm/i915/gt/intel_migrate.c | 23 ++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/intel_migrate.c b/drivers/gpu/drm/i915/gt/intel_migrate.c index a69b244f14d0..9a0814422ba4 100644 --- a/drivers/gpu/drm/i915/gt/intel_migrate.c +++ b/drivers/gpu/drm/i915/gt/intel_migrate.c @@ -708,7 +708,7 @@ intel_context_migrate_copy(struct intel_context *ce, u8 src_access, dst_access; struct i915_request *rq; int src_sz, dst_sz; - bool ccs_is_src; + bool ccs_is_src, overwrite_ccs; int err; GEM_BUG_ON(ce->vm != ce->engine->gt->migrate.context->vm); @@ -749,6 +749,8 @@ intel_context_migrate_copy(struct intel_context *ce, get_ccs_sg_sgt(_ccs, bytes_to_cpy); } + overwrite_ccs = HAS_FLAT_CCS(i915) && !ccs_bytes_to_cpy && dst_is_lmem; + src_offset = 0; dst_offset = CHUNK_SZ; if (HAS_64K_PAGES(ce->engine->i915)) { @@ -852,6 +854,25 @@ intel_context_migrate_copy(struct intel_context *ce, if (err) goto out_rq; ccs_bytes_to_cpy -= ccs_sz; + } else if (overwrite_ccs) { + err = rq->engine->emit_flush(rq, EMIT_INVALIDATE); + if (err) + goto out_rq; + + /* +* While we can't always restore/manage the CCS state, +* we still need to ensure we don't leak the CCS state +* from the previous user, so make sure we overwrite it +* with something. +*/ + err = emit_copy_ccs(rq, dst_offset, INDIRECT_ACCESS, + dst_offset, DIRECT_ACCESS, len); + if (err) + goto out_rq; + + err = rq->engine->emit_flush(rq, EMIT_INVALIDATE); + if (err) + goto out_rq; } /* Arbitration is re-enabled between requests. */ -- 2.37.1
[PATCH] dt-bindings: display: use spi-peripheral-props.yaml
Instead of listing directly properties typical for SPI peripherals, reference the spi-peripheral-props.yaml schema. This allows using all properties typical for SPI-connected devices, even these which device bindings author did not tried yet. Remove the spi-* properties which now come via spi-peripheral-props.yaml schema, except for the cases when device schema adds some constraints like maximum frequency. While changing additionalProperties->unevaluatedProperties, put it in typical place, just before example DTS. The sitronix,st7735r references also panel-common.yaml and lists explicitly allowed properties, thus here reference only spi-peripheral-props.yaml for purpose of documenting the SPI slave device and bringing spi-max-frequency type validation. Signed-off-by: Krzysztof Kozlowski --- Technically, this depends on [1] merged to SPI tree, if we want to preserve existing behavior of not allowing SPI CPHA and CPOL in each of schemas in this patch. If this patch comes independently via different tree, the SPI CPHA and CPOL will be allowed for brief period of time, before [1] is merged. This will not have negative impact, just DT schema checks will be loosened for that period. [1] https://lore.kernel.org/all/20220722191539.90641-2-krzysztof.kozlow...@linaro.org/ --- .../devicetree/bindings/display/panel/lg,lg4573.yaml | 2 +- .../devicetree/bindings/display/sitronix,st7735r.yaml | 1 + .../devicetree/bindings/display/solomon,ssd1307fb.yaml | 7 +++ 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/display/panel/lg,lg4573.yaml b/Documentation/devicetree/bindings/display/panel/lg,lg4573.yaml index b4314ce7b411..ee357e139ac0 100644 --- a/Documentation/devicetree/bindings/display/panel/lg,lg4573.yaml +++ b/Documentation/devicetree/bindings/display/panel/lg,lg4573.yaml @@ -15,13 +15,13 @@ maintainers: allOf: - $ref: panel-common.yaml# + - $ref: /schemas/spi/spi-peripheral-props.yaml# properties: compatible: const: lg,lg4573 reg: true - spi-max-frequency: true required: - compatible diff --git a/Documentation/devicetree/bindings/display/sitronix,st7735r.yaml b/Documentation/devicetree/bindings/display/sitronix,st7735r.yaml index 157b1a7b18f9..53f181ef3670 100644 --- a/Documentation/devicetree/bindings/display/sitronix,st7735r.yaml +++ b/Documentation/devicetree/bindings/display/sitronix,st7735r.yaml @@ -15,6 +15,7 @@ description: allOf: - $ref: panel/panel-common.yaml# + - $ref: /schemas/spi/spi-peripheral-props.yaml# properties: compatible: diff --git a/Documentation/devicetree/bindings/display/solomon,ssd1307fb.yaml b/Documentation/devicetree/bindings/display/solomon,ssd1307fb.yaml index 3fbd87c2c120..669f70b1b4c4 100644 --- a/Documentation/devicetree/bindings/display/solomon,ssd1307fb.yaml +++ b/Documentation/devicetree/bindings/display/solomon,ssd1307fb.yaml @@ -49,9 +49,6 @@ properties: vbat-supply: description: The supply for VBAT - # Only required for SPI - spi-max-frequency: true - solomon,height: $ref: /schemas/types.yaml#/definitions/uint32 default: 16 @@ -153,6 +150,8 @@ required: - reg allOf: + - $ref: /schemas/spi/spi-peripheral-props.yaml# + - if: properties: compatible: @@ -223,7 +222,7 @@ allOf: solomon,dclk-frq: default: 10 -additionalProperties: false +unevaluatedProperties: false examples: - | -- 2.34.1
[PATCH v5 10/10] drm: rcar-du: Add RZ/G2L DU Support
The LCD controller is composed of Frame Compression Processor (FCPVD), Video Signal Processor (VSPD), and Display Unit (DU). It has DPI/DSI interfaces and supports a maximum resolution of 1080p along with 2 RPFs to support blending of two picture layers and raster operations (ROPs). The DU part is similar to RCar like DU is connected to VSPD, so most of the framework related functionality is based on RCar DU. Signed-off-by: Biju Das --- v4->v5: * Started using RCar DU libs(kms, vsp and encoder) * Started using rcar_du_device, rcar_du_write, rcar_du_crtc, rcar_du_format_info and rcar_du_encoder. v3->v4: * Removed rzg2l_du_group.h and struct rzg2l_du_group * Renamed __rzg2l_du_group_start_stop->rzg2l_du_start_stop * Removed rzg2l_du_group_restart * Updated rzg2l_du_crtc_set_display_timing * Removed mode_valid callback. * Updated rzg2l_du_crtc_create() parameters * Updated compatible * Removed RZG2L_DU_MAX_GROUPS v3: * New patch after removing all the indirections and by adding new DRM driver. --- drivers/gpu/drm/rcar-du/Kconfig| 17 +- drivers/gpu/drm/rcar-du/Makefile | 13 + drivers/gpu/drm/rcar-du/rzg2l_du_crtc.c| 718 + drivers/gpu/drm/rcar-du/rzg2l_du_crtc.h| 26 + drivers/gpu/drm/rcar-du/rzg2l_du_drv.c | 206 ++ drivers/gpu/drm/rcar-du/rzg2l_du_drv.h | 20 + drivers/gpu/drm/rcar-du/rzg2l_du_encoder.c | 26 + drivers/gpu/drm/rcar-du/rzg2l_du_encoder.h | 19 + drivers/gpu/drm/rcar-du/rzg2l_du_kms.c | 158 + drivers/gpu/drm/rcar-du/rzg2l_du_kms.h | 17 + drivers/gpu/drm/rcar-du/rzg2l_du_regs.h| 67 ++ drivers/gpu/drm/rcar-du/rzg2l_du_vsp.c | 82 +++ drivers/gpu/drm/rcar-du/rzg2l_du_vsp.h | 29 + 13 files changed, 1396 insertions(+), 2 deletions(-) create mode 100644 drivers/gpu/drm/rcar-du/rzg2l_du_crtc.c create mode 100644 drivers/gpu/drm/rcar-du/rzg2l_du_crtc.h create mode 100644 drivers/gpu/drm/rcar-du/rzg2l_du_drv.c create mode 100644 drivers/gpu/drm/rcar-du/rzg2l_du_drv.h create mode 100644 drivers/gpu/drm/rcar-du/rzg2l_du_encoder.c create mode 100644 drivers/gpu/drm/rcar-du/rzg2l_du_encoder.h create mode 100644 drivers/gpu/drm/rcar-du/rzg2l_du_kms.c create mode 100644 drivers/gpu/drm/rcar-du/rzg2l_du_kms.h create mode 100644 drivers/gpu/drm/rcar-du/rzg2l_du_regs.h create mode 100644 drivers/gpu/drm/rcar-du/rzg2l_du_vsp.c create mode 100644 drivers/gpu/drm/rcar-du/rzg2l_du_vsp.h diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig index f8e1341be5f8..c45416197a2b 100644 --- a/drivers/gpu/drm/rcar-du/Kconfig +++ b/drivers/gpu/drm/rcar-du/Kconfig @@ -11,6 +11,18 @@ config DRM_RCAR_DU Choose this option if you have an R-Car chipset. If M is selected the module will be called rcar-du-drm. +config DRM_RZG2L_DU + tristate "DRM Support for RZ/G2L DU" + depends on DRM && OF + depends on ARM || ARM64 + depends on ARCH_RENESAS || COMPILE_TEST + select DRM_KMS_HELPER + select DRM_GEM_CMA_HELPER + select VIDEOMODE_HELPERS + help + Choose this option if you have an RZ/G2L chipset. + If M is selected the module will be called rzg2l-du-drm. + config DRM_RCAR_USE_CMM bool "R-Car DU Color Management Module (CMM) Support" depends on DRM_RCAR_DU @@ -62,8 +74,9 @@ config DRM_RZG2L_MIPI_DSI config DRM_RCAR_VSP bool "R-Car DU VSP Compositor Support" if ARM default y if ARM64 - depends on DRM_RCAR_DU + depends on DRM_RCAR_DU || DRM_RZG2L_DU depends on VIDEO_RENESAS_VSP1=y || (VIDEO_RENESAS_VSP1 && DRM_RCAR_DU=m) + depends on VIDEO_RENESAS_VSP1=y || (VIDEO_RENESAS_VSP1 && DRM_RZG2L_DU=m) help Enable support to expose the R-Car VSP Compositor as KMS planes. @@ -75,7 +88,7 @@ config DRM_RCAR_WRITEBACK config DRM_RCAR_LIB bool default y - depends on DRM_RCAR_DU + depends on DRM_RCAR_DU || DRM_RZG2L_DU config DRM_RCAR_VSP_LIB bool diff --git a/drivers/gpu/drm/rcar-du/Makefile b/drivers/gpu/drm/rcar-du/Makefile index cee1f69926db..445ff4e7186f 100644 --- a/drivers/gpu/drm/rcar-du/Makefile +++ b/drivers/gpu/drm/rcar-du/Makefile @@ -19,6 +19,19 @@ obj-$(CONFIG_DRM_RCAR_DW_HDMI) += rcar_dw_hdmi.o obj-$(CONFIG_DRM_RCAR_LVDS)+= rcar_lvds.o obj-$(CONFIG_DRM_RCAR_MIPI_DSI)+= rcar_mipi_dsi.o +rzg2l-du-drm-y := rzg2l_du_crtc.o \ + rzg2l_du_drv.o \ + rzg2l_du_encoder.o \ + rzg2l_du_kms.o \ + +rzg2l-du-drm-$(CONFIG_DRM_RCAR_LIB) += rcar_du_encoder_lib.o \ + rcar_du_kms_lib.o + +rzg2l-du-drm-$(CONFIG_DRM_RCAR_VSP)+= rzg2l_du_vsp.o +rzg2l-du-drm-$(CONFIG_DRM_RCAR_VSP_LIB)+= rcar_du_vsp_lib.o +rzg2l-du-drm-$(CONFIG_DRM_RCAR_WRITEBACK) += rcar_du_writeback.o + +obj-$(CONFIG_DRM_RZG2L_DU) += rzg2l-du-drm.o
[PATCH v5 05/10] drm: rcar-du: Add rcar_du_lib_mode_cfg_helper_fns()
Add rcar_du_lib_mode_cfg_helper_fns() in RCar DU kms lib to get the pointer to rcar_du_mode_config_helper, so that both rcar_du_atomic_ commit_tail() and rcar_du_mode_config_helper can be reused by rcar_du_modeset_init() and rzg2l_du_modeset_init(). Signed-off-by: Biju Das --- v5: * New patch --- drivers/gpu/drm/rcar-du/rcar_du_kms.c | 44 +- drivers/gpu/drm/rcar-du/rcar_du_kms_lib.c | 56 +++ drivers/gpu/drm/rcar-du/rcar_du_kms_lib.h | 3 ++ 3 files changed, 60 insertions(+), 43 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c index 9d65a7d6d96e..ed8d14701178 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c @@ -64,52 +64,10 @@ static int rcar_du_atomic_check(struct drm_device *dev, return rcar_du_atomic_check_planes(dev, state); } -static void rcar_du_atomic_commit_tail(struct drm_atomic_state *old_state) -{ - struct drm_device *dev = old_state->dev; - struct rcar_du_device *rcdu = to_rcar_du_device(dev); - struct drm_crtc_state *crtc_state; - struct drm_crtc *crtc; - unsigned int i; - - /* -* Store RGB routing to DPAD0 and DPAD1, the hardware will be configured -* when starting the CRTCs. -*/ - rcdu->dpad1_source = -1; - - for_each_new_crtc_in_state(old_state, crtc, crtc_state, i) { - struct rcar_du_crtc_state *rcrtc_state = - to_rcar_crtc_state(crtc_state); - struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc); - - if (rcrtc_state->outputs & BIT(RCAR_DU_OUTPUT_DPAD0)) - rcdu->dpad0_source = rcrtc->index; - - if (rcrtc_state->outputs & BIT(RCAR_DU_OUTPUT_DPAD1)) - rcdu->dpad1_source = rcrtc->index; - } - - /* Apply the atomic update. */ - drm_atomic_helper_commit_modeset_disables(dev, old_state); - drm_atomic_helper_commit_planes(dev, old_state, - DRM_PLANE_COMMIT_ACTIVE_ONLY); - drm_atomic_helper_commit_modeset_enables(dev, old_state); - - drm_atomic_helper_commit_hw_done(old_state); - drm_atomic_helper_wait_for_flip_done(dev, old_state); - - drm_atomic_helper_cleanup_planes(dev, old_state); -} - /* - * Initialization */ -static const struct drm_mode_config_helper_funcs rcar_du_mode_config_helper = { - .atomic_commit_tail = rcar_du_atomic_commit_tail, -}; - static const struct drm_mode_config_funcs rcar_du_mode_config_funcs = { .fb_create = rcar_du_fb_create, .atomic_check = rcar_du_atomic_check, @@ -415,7 +373,7 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu) dev->mode_config.min_height = 0; dev->mode_config.normalize_zpos = true; dev->mode_config.funcs = _du_mode_config_funcs; - dev->mode_config.helper_private = _du_mode_config_helper; + dev->mode_config.helper_private = rcar_du_lib_mode_cfg_helper_fns(); if (rcdu->info->gen < 3) { dev->mode_config.max_width = 4095; diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms_lib.c b/drivers/gpu/drm/rcar-du/rcar_du_kms_lib.c index d8f778a7b6db..a1027436cfe3 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms_lib.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms_lib.c @@ -461,3 +461,59 @@ rcar_du_lib_fb_create(struct drm_device *dev, struct drm_file *file_priv, return drm_gem_fb_create(dev, file_priv, mode_cmd); } + +/* - + * Atomic Check and Update + */ + +static void rcar_du_atomic_commit_tail(struct drm_atomic_state *old_state) +{ + struct drm_device *dev = old_state->dev; + struct rcar_du_device *rcdu = to_rcar_du_device(dev); + struct drm_crtc_state *crtc_state; + struct drm_crtc *crtc; + unsigned int i; + + /* +* Store RGB routing to DPAD0 and DPAD1, the hardware will be configured +* when starting the CRTCs. +*/ + rcdu->dpad1_source = -1; + + for_each_new_crtc_in_state(old_state, crtc, crtc_state, i) { + struct rcar_du_crtc_state *rcrtc_state = + to_rcar_crtc_state(crtc_state); + struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc); + + if (rcrtc_state->outputs & BIT(RCAR_DU_OUTPUT_DPAD0)) + rcdu->dpad0_source = rcrtc->index; + + if (rcrtc_state->outputs & BIT(RCAR_DU_OUTPUT_DPAD1)) + rcdu->dpad1_source = rcrtc->index; + } + + /* Apply the atomic update. */ + drm_atomic_helper_commit_modeset_disables(dev, old_state); + drm_atomic_helper_commit_planes(dev, old_state, + DRM_PLANE_COMMIT_ACTIVE_ONLY); +
[PATCH v5 06/10] drm: rcar-du: Move rcar_du_encoders_init()
RZ/G2L supports only DSI and DPI. Add rcar_du_encoders_init() to handle the pointer to du_output_name(), so that we can share du_encoders_init() between RCar and RZ/G2L kms drivers. Signed-off-by: Biju Das --- v5: * New patch --- drivers/gpu/drm/rcar-du/rcar_du_kms.c | 92 +--- drivers/gpu/drm/rcar-du/rcar_du_kms_lib.c | 100 ++ drivers/gpu/drm/rcar-du/rcar_du_kms_lib.h | 6 ++ 3 files changed, 108 insertions(+), 90 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c index ed8d14701178..7586520e1871 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c @@ -74,95 +74,6 @@ static const struct drm_mode_config_funcs rcar_du_mode_config_funcs = { .atomic_commit = drm_atomic_helper_commit, }; -static int rcar_du_encoders_init_one(struct rcar_du_device *rcdu, -enum rcar_du_output output, -struct of_endpoint *ep) -{ - struct device_node *entity; - int ret; - - /* Locate the connected entity and initialize the encoder. */ - entity = of_graph_get_remote_port_parent(ep->local_node); - if (!entity) { - dev_dbg(rcdu->dev, "unconnected endpoint %pOF, skipping\n", - ep->local_node); - return -ENODEV; - } - - if (!of_device_is_available(entity)) { - dev_dbg(rcdu->dev, - "connected entity %pOF is disabled, skipping\n", - entity); - of_node_put(entity); - return -ENODEV; - } - - ret = rcar_du_encoder_init(rcdu, output, entity); - if (ret && ret != -EPROBE_DEFER && ret != -ENOLINK) - dev_warn(rcdu->dev, -"failed to initialize encoder %pOF on output %s (%d), skipping\n", -entity, rcar_du_output_name(output), ret); - - of_node_put(entity); - - return ret; -} - -static int rcar_du_encoders_init(struct rcar_du_device *rcdu) -{ - struct device_node *np = rcdu->dev->of_node; - struct device_node *ep_node; - unsigned int num_encoders = 0; - - /* -* Iterate over the endpoints and create one encoder for each output -* pipeline. -*/ - for_each_endpoint_of_node(np, ep_node) { - enum rcar_du_output output; - struct of_endpoint ep; - unsigned int i; - int ret; - - ret = of_graph_parse_endpoint(ep_node, ); - if (ret < 0) { - of_node_put(ep_node); - return ret; - } - - /* Find the output route corresponding to the port number. */ - for (i = 0; i < RCAR_DU_OUTPUT_MAX; ++i) { - if (rcdu->info->routes[i].possible_crtcs && - rcdu->info->routes[i].port == ep.port) { - output = i; - break; - } - } - - if (i == RCAR_DU_OUTPUT_MAX) { - dev_warn(rcdu->dev, -"port %u references unexisting output, skipping\n", -ep.port); - continue; - } - - /* Process the output pipeline. */ - ret = rcar_du_encoders_init_one(rcdu, output, ); - if (ret < 0) { - if (ret == -EPROBE_DEFER) { - of_node_put(ep_node); - return ret; - } - - continue; - } - - num_encoders++; - } - - return num_encoders; -} - static int rcar_du_properties_init(struct rcar_du_device *rcdu) { /* @@ -462,7 +373,8 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu) } /* Initialize the encoders. */ - ret = rcar_du_encoders_init(rcdu); + ret = rcar_du_encoders_init(rcdu, rcar_du_output_name, + rcar_du_encoder_init); if (ret < 0) return ret; diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms_lib.c b/drivers/gpu/drm/rcar-du/rcar_du_kms_lib.c index a1027436cfe3..d41fee590ee4 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms_lib.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms_lib.c @@ -517,3 +517,103 @@ rcar_du_lib_mode_cfg_helper_fns(void) { return _du_mode_config_helper; } + +static int +rcar_du_encoders_init_one(struct rcar_du_device *rcdu, + enum rcar_du_output output, + struct of_endpoint *ep, + const char *output_name, + int (*rcar_du_encoder_init_fn)(struct rcar_du_device *r, +
[PATCH v5 07/10] drm: rcar-du: Move rcar_du_properties_init()
Move rcar_du_properties_init() to RCar DU kms lib, so that it can be shared by both RCar and RZ/G2L kms drivers. Signed-off-by: Biju Das --- v5: * New patch --- drivers/gpu/drm/rcar-du/rcar_du_kms.c | 16 drivers/gpu/drm/rcar-du/rcar_du_kms_lib.c | 16 drivers/gpu/drm/rcar-du/rcar_du_kms_lib.h | 2 ++ 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c index 7586520e1871..b3ebe694be6e 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c @@ -74,22 +74,6 @@ static const struct drm_mode_config_funcs rcar_du_mode_config_funcs = { .atomic_commit = drm_atomic_helper_commit, }; -static int rcar_du_properties_init(struct rcar_du_device *rcdu) -{ - /* -* The color key is expressed as an RGB888 triplet stored in a 32-bit -* integer in XRGB format. Bit 24 is used as a flag to disable (0) -* or enable source color keying (1). -*/ - rcdu->props.colorkey = - drm_property_create_range(>ddev, 0, "colorkey", - 0, 0x01ff); - if (rcdu->props.colorkey == NULL) - return -ENOMEM; - - return 0; -} - static int rcar_du_vsps_init(struct rcar_du_device *rcdu) { const struct device_node *np = rcdu->dev->of_node; diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms_lib.c b/drivers/gpu/drm/rcar-du/rcar_du_kms_lib.c index d41fee590ee4..a56f3d6db321 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms_lib.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms_lib.c @@ -617,3 +617,19 @@ int rcar_du_encoders_init(struct rcar_du_device *rcdu, return num_encoders; } + +int rcar_du_properties_init(struct rcar_du_device *rcdu) +{ + /* +* The color key is expressed as an RGB888 triplet stored in a 32-bit +* integer in XRGB format. Bit 24 is used as a flag to disable (0) +* or enable source color keying (1). +*/ + rcdu->props.colorkey = + drm_property_create_range(>ddev, 0, "colorkey", + 0, 0x01ff); + if (rcdu->props.colorkey == NULL) + return -ENOMEM; + + return 0; +} diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms_lib.h b/drivers/gpu/drm/rcar-du/rcar_du_kms_lib.h index 02d6ed5aa154..b04c42bbae5c 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms_lib.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms_lib.h @@ -52,4 +52,6 @@ int rcar_du_encoders_init(struct rcar_du_device *rcdu, enum rcar_du_output output, struct device_node *enc_node)); +int rcar_du_properties_init(struct rcar_du_device *rcdu); + #endif /* __RCAR_DU_KMS_LIB_H__ */ -- 2.25.1
[PATCH v5 09/10] dt-bindings: display: Document Renesas RZ/G2L DU bindings
The RZ/G2L LCD controller is composed of Frame Compression Processor (FCPVD), Video Signal Processor (VSPD), and Display Unit (DU). The DU module supports the following hardware features − Display Parallel Interface (DPI) and MIPI LINK Video Interface − Display timing master − Generates video timings − Selecting the polarity of output DCLK, HSYNC, VSYNC, and DE − Supports Progressive − Input data format (from VSPD): RGB888, RGB666 − Output data format: same as Input data format − Supporting Full HD (1920 pixels x 1080 lines) for MIPI-DSI Output − Supporting WXGA (1280 pixels x 800 lines) for Parallel Output This patch document DU module found on RZ/G2L LCDC. Signed-off-by: Biju Das Reviewed-by: Rob Herring --- v4->v5: * Added Rb tag from Rob. v3->v4: * Changed compatible name from renesas,du-r9a07g044->renesas,r9a07g044-du * started using same compatible for RZ/G2{L,LC} v3: New patch --- .../bindings/display/renesas,rzg2l-du.yaml| 124 ++ 1 file changed, 124 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/renesas,rzg2l-du.yaml diff --git a/Documentation/devicetree/bindings/display/renesas,rzg2l-du.yaml b/Documentation/devicetree/bindings/display/renesas,rzg2l-du.yaml new file mode 100644 index ..7626043debd8 --- /dev/null +++ b/Documentation/devicetree/bindings/display/renesas,rzg2l-du.yaml @@ -0,0 +1,124 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/renesas,rzg2l-du.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Renesas RZ/G2L Display Unit (DU) + +maintainers: + - Laurent Pinchart + - Biju Das + +description: | + These DT bindings describe the Display Unit embedded in the Renesas RZ/G2L + and RZ/V2L SoCs. + +properties: + compatible: +enum: + - renesas,r9a07g044-du # RZ/G2{L,LC} + + reg: +maxItems: 1 + + interrupts: +maxItems: 1 + + clocks: +items: + - description: Main clock + - description: Register access clock + - description: Video clock + + clock-names: +items: + - const: aclk + - const: pclk + - const: vclk + + resets: +maxItems: 1 + + power-domains: +maxItems: 1 + + ports: +$ref: /schemas/graph.yaml#/properties/ports +description: | + The connections to the DU output video ports are modeled using the OF + graph bindings specified in Documentation/devicetree/bindings/graph.txt. + The number of ports and their assignment are model-dependent. Each port + shall have a single endpoint. + +patternProperties: + "^port@[0-1]$": +$ref: /schemas/graph.yaml#/properties/port +unevaluatedProperties: false + +required: + - port@0 + +unevaluatedProperties: false + + renesas,vsps: +$ref: "/schemas/types.yaml#/definitions/phandle-array" +items: + items: +- description: phandle to VSP instance that serves the DU channel +- description: Channel index identifying the LIF instance in that VSP +description: + A list of phandle and channel index tuples to the VSPs that handle the + memory interfaces for the DU channels. + +required: + - compatible + - reg + - interrupts + - clocks + - clock-names + - resets + - power-domains + - ports + - renesas,vsps + +additionalProperties: false + +examples: + # RZ/G2L DU + - | +#include +#include + +display@1089 { +compatible = "renesas,r9a07g044-du"; +reg = <0x1089 0x1>; +interrupts = ; +clocks = < CPG_MOD R9A07G044_LCDC_CLK_A>, + < CPG_MOD R9A07G044_LCDC_CLK_P>, + < CPG_MOD R9A07G044_LCDC_CLK_D>; +clock-names = "aclk", "pclk", "vclk"; +resets = < R9A07G044_LCDC_RESET_N>; +power-domains = <>; + +renesas,vsps = < 0>; + +ports { +#address-cells = <1>; +#size-cells = <0>; + +port@0 { +reg = <0>; +endpoint { +remote-endpoint = <_in>; +}; +}; +port@1 { +reg = <1>; +endpoint { +}; +}; +}; +}; + +... -- 2.25.1
[PATCH v5 01/10] drm: rcar-du: Move rcar_du_vsp_plane_prepare_fb()
Move rcar_du_vsp_plane_prepare_fb() to RCar DU vsp lib so that both RCar and RZ/G2L DU vsp drivers can share this function. Signed-off-by: Biju Das --- v5: * New patch --- drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 21 - drivers/gpu/drm/rcar-du/rcar_du_vsp_lib.c | 21 + drivers/gpu/drm/rcar-du/rcar_du_vsp_lib.h | 7 +++ 3 files changed, 28 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c index d192c31a5fe1..72128915a2ff 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c @@ -124,27 +124,6 @@ static void rcar_du_vsp_plane_setup(struct rcar_du_vsp_plane *plane) plane->index, ); } -static int rcar_du_vsp_plane_prepare_fb(struct drm_plane *plane, - struct drm_plane_state *state) -{ - struct rcar_du_vsp_plane_state *rstate = to_rcar_vsp_plane_state(state); - struct rcar_du_vsp *vsp = to_rcar_vsp_plane(plane)->vsp; - int ret; - - /* -* There's no need to prepare (and unprepare) the framebuffer when the -* plane is not visible, as it will not be displayed. -*/ - if (!state->visible) - return 0; - - ret = rcar_du_vsp_map_fb(vsp, state->fb, rstate->sg_tables); - if (ret < 0) - return ret; - - return drm_gem_plane_helper_prepare_fb(plane, state); -} - static void rcar_du_vsp_plane_cleanup_fb(struct drm_plane *plane, struct drm_plane_state *state) { diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp_lib.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp_lib.c index 80da12f1fe71..40d44bf521c0 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_vsp_lib.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp_lib.c @@ -147,6 +147,27 @@ int rcar_du_vsp_map_fb(struct rcar_du_vsp *vsp, struct drm_framebuffer *fb, return ret; } +int rcar_du_vsp_plane_prepare_fb(struct drm_plane *plane, +struct drm_plane_state *state) +{ + struct rcar_du_vsp_plane_state *rstate = to_rcar_vsp_plane_state(state); + struct rcar_du_vsp *vsp = to_rcar_vsp_plane(plane)->vsp; + int ret; + + /* +* There's no need to prepare (and unprepare) the framebuffer when the +* plane is not visible, as it will not be displayed. +*/ + if (!state->visible) + return 0; + + ret = rcar_du_vsp_map_fb(vsp, state->fb, rstate->sg_tables); + if (ret < 0) + return ret; + + return drm_gem_plane_helper_prepare_fb(plane, state); +} + void rcar_du_vsp_unmap_fb(struct rcar_du_vsp *vsp, struct drm_framebuffer *fb, struct sg_table sg_tables[3]) { diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp_lib.h b/drivers/gpu/drm/rcar-du/rcar_du_vsp_lib.h index abfde19fd1a3..d79cdf7d7316 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_vsp_lib.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp_lib.h @@ -66,6 +66,8 @@ void rcar_du_vsp_unmap_fb(struct rcar_du_vsp *vsp, struct drm_framebuffer *fb, int rcar_du_lib_vsp_init(struct rcar_du_vsp *vsp, struct device_node *np, unsigned int crtcs, const struct drm_plane_helper_funcs *rcar_du_vsp_plane_helper_funcs); +int rcar_du_vsp_plane_prepare_fb(struct drm_plane *plane, +struct drm_plane_state *state); #else static inline void rcar_du_vsp_disable(struct rcar_du_crtc *crtc) { }; static inline void rcar_du_vsp_atomic_begin(struct rcar_du_crtc *crtc) { }; @@ -88,6 +90,11 @@ rcar_du_lib_vsp_init(struct rcar_du_vsp *vsp, struct device_node *np, { return -ENXIO; } +static inline int rcar_du_vsp_plane_prepare_fb(struct drm_plane *plane, + struct drm_plane_state *state) +{ + return -ENXIO; +} #endif #endif /* __RCAR_DU_VSP_LIB_H__ */ -- 2.25.1
[PATCH v5 08/10] drm: rcar-du: Add rcar_du_lib_vsps_init()
Add rcar_du_lib_vsps_init() to RCar DU kms lib to handle both rcar_du_vsp_init() and rzg2l_du_vsp_init(). Signed-off-by: Biju Das --- v5: * New patch --- drivers/gpu/drm/rcar-du/rcar_du_kms.c | 88 +- drivers/gpu/drm/rcar-du/rcar_du_kms_lib.c | 89 +++ drivers/gpu/drm/rcar-du/rcar_du_kms_lib.h | 5 ++ 3 files changed, 95 insertions(+), 87 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c index b3ebe694be6e..73269b7e067e 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c @@ -74,92 +74,6 @@ static const struct drm_mode_config_funcs rcar_du_mode_config_funcs = { .atomic_commit = drm_atomic_helper_commit, }; -static int rcar_du_vsps_init(struct rcar_du_device *rcdu) -{ - const struct device_node *np = rcdu->dev->of_node; - const char *vsps_prop_name = "renesas,vsps"; - struct of_phandle_args args; - struct { - struct device_node *np; - unsigned int crtcs_mask; - } vsps[RCAR_DU_MAX_VSPS] = { { NULL, }, }; - unsigned int vsps_count = 0; - unsigned int cells; - unsigned int i; - int ret; - - /* -* First parse the DT vsps property to populate the list of VSPs. Each -* entry contains a pointer to the VSP DT node and a bitmask of the -* connected DU CRTCs. -*/ - ret = of_property_count_u32_elems(np, vsps_prop_name); - if (ret < 0) { - /* Backward compatibility with old DTBs. */ - vsps_prop_name = "vsps"; - ret = of_property_count_u32_elems(np, vsps_prop_name); - } - cells = ret / rcdu->num_crtcs - 1; - if (cells > 1) - return -EINVAL; - - for (i = 0; i < rcdu->num_crtcs; ++i) { - unsigned int j; - - ret = of_parse_phandle_with_fixed_args(np, vsps_prop_name, - cells, i, ); - if (ret < 0) - goto error; - - /* -* Add the VSP to the list or update the corresponding existing -* entry if the VSP has already been added. -*/ - for (j = 0; j < vsps_count; ++j) { - if (vsps[j].np == args.np) - break; - } - - if (j < vsps_count) - of_node_put(args.np); - else - vsps[vsps_count++].np = args.np; - - vsps[j].crtcs_mask |= BIT(i); - - /* -* Store the VSP pointer and pipe index in the CRTC. If the -* second cell of the 'renesas,vsps' specifier isn't present, -* default to 0 to remain compatible with older DT bindings. -*/ - rcdu->crtcs[i].vsp = >vsps[j]; - rcdu->crtcs[i].vsp_pipe = cells >= 1 ? args.args[0] : 0; - } - - /* -* Then initialize all the VSPs from the node pointers and CRTCs bitmask -* computed previously. -*/ - for (i = 0; i < vsps_count; ++i) { - struct rcar_du_vsp *vsp = >vsps[i]; - - vsp->index = i; - vsp->dev = rcdu; - - ret = rcar_du_vsp_init(vsp, vsps[i].np, vsps[i].crtcs_mask); - if (ret < 0) - goto error; - } - - return 0; - -error: - for (i = 0; i < ARRAY_SIZE(vsps); ++i) - of_node_put(vsps[i].np); - - return ret; -} - static int rcar_du_cmm_init(struct rcar_du_device *rcdu) { const struct device_node *np = rcdu->dev->of_node; @@ -331,7 +245,7 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu) /* Initialize the compositors. */ if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE)) { - ret = rcar_du_vsps_init(rcdu); + ret = rcar_du_lib_vsps_init(rcdu, rcar_du_vsp_init); if (ret < 0) return ret; } diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms_lib.c b/drivers/gpu/drm/rcar-du/rcar_du_kms_lib.c index a56f3d6db321..c9fa4d1c78fd 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms_lib.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms_lib.c @@ -633,3 +633,92 @@ int rcar_du_properties_init(struct rcar_du_device *rcdu) return 0; } + +int rcar_du_lib_vsps_init(struct rcar_du_device *rcdu, + int (*rcar_du_vsp_init_fn)(struct rcar_du_vsp *vsp, +struct device_node *np, +unsigned int crtcs)) +{ + const struct device_node *np = rcdu->dev->of_node; + const char *vsps_prop_name = "renesas,vsps"; + struct of_phandle_args args; + struct { + struct device_node *np; +
[PATCH v5 04/10] drm: rcar-du: Add rcar_du_lib_fb_create()
Move the common code from rcar_du_fb_create->rcar_du_lib_fb_create, so that rzg2l_du_fb_create() can reuse the common code. Signed-off-by: Biju Das --- v5: * New patch --- drivers/gpu/drm/rcar-du/rcar_du_kms.c | 64 + drivers/gpu/drm/rcar-du/rcar_du_kms_lib.c | 69 +++ drivers/gpu/drm/rcar-du/rcar_du_kms_lib.h | 4 ++ 3 files changed, 74 insertions(+), 63 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c index ea2b7d5f1c23..9d65a7d6d96e 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c @@ -41,69 +41,7 @@ static struct drm_framebuffer * rcar_du_fb_create(struct drm_device *dev, struct drm_file *file_priv, const struct drm_mode_fb_cmd2 *mode_cmd) { - struct rcar_du_device *rcdu = to_rcar_du_device(dev); - const struct rcar_du_format_info *format; - unsigned int chroma_pitch; - unsigned int max_pitch; - unsigned int align; - unsigned int i; - - format = rcar_du_format_info(mode_cmd->pixel_format); - if (format == NULL) { - dev_dbg(dev->dev, "unsupported pixel format %08x\n", - mode_cmd->pixel_format); - return ERR_PTR(-EINVAL); - } - - if (rcdu->info->gen < 3) { - /* -* On Gen2 the DU limits the pitch to 4095 pixels and requires -* buffers to be aligned to a 16 pixels boundary (or 128 bytes -* on some platforms). -*/ - unsigned int bpp = format->planes == 1 ? format->bpp / 8 : 1; - - max_pitch = 4095 * bpp; - - if (rcar_du_needs(rcdu, RCAR_DU_QUIRK_ALIGN_128B)) - align = 128; - else - align = 16 * bpp; - } else { - /* -* On Gen3 the memory interface is handled by the VSP that -* limits the pitch to 65535 bytes and has no alignment -* constraint. -*/ - max_pitch = 65535; - align = 1; - } - - if (mode_cmd->pitches[0] & (align - 1) || - mode_cmd->pitches[0] > max_pitch) { - dev_dbg(dev->dev, "invalid pitch value %u\n", - mode_cmd->pitches[0]); - return ERR_PTR(-EINVAL); - } - - /* -* Calculate the chroma plane(s) pitch using the horizontal subsampling -* factor. For semi-planar formats, the U and V planes are combined, the -* pitch must thus be doubled. -*/ - chroma_pitch = mode_cmd->pitches[0] / format->hsub; - if (format->planes == 2) - chroma_pitch *= 2; - - for (i = 1; i < format->planes; ++i) { - if (mode_cmd->pitches[i] != chroma_pitch) { - dev_dbg(dev->dev, - "luma and chroma pitches are not compatible\n"); - return ERR_PTR(-EINVAL); - } - } - - return drm_gem_fb_create(dev, file_priv, mode_cmd); + return rcar_du_lib_fb_create(dev, file_priv, mode_cmd); } /* - diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms_lib.c b/drivers/gpu/drm/rcar-du/rcar_du_kms_lib.c index 6461b99e08dc..d8f778a7b6db 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms_lib.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms_lib.c @@ -392,3 +392,72 @@ int rcar_du_dumb_create(struct drm_file *file, struct drm_device *dev, return drm_gem_cma_dumb_create_internal(file, dev, args); } + +struct drm_framebuffer * +rcar_du_lib_fb_create(struct drm_device *dev, struct drm_file *file_priv, + const struct drm_mode_fb_cmd2 *mode_cmd) +{ + struct rcar_du_device *rcdu = to_rcar_du_device(dev); + const struct rcar_du_format_info *format; + unsigned int chroma_pitch; + unsigned int max_pitch; + unsigned int align; + unsigned int i; + + format = rcar_du_format_info(mode_cmd->pixel_format); + if (format == NULL) { + dev_dbg(dev->dev, "unsupported pixel format %08x\n", + mode_cmd->pixel_format); + return ERR_PTR(-EINVAL); + } + + if (rcdu->info->gen < 3) { + /* +* On Gen2 the DU limits the pitch to 4095 pixels and requires +* buffers to be aligned to a 16 pixels boundary (or 128 bytes +* on some platforms). +*/ + unsigned int bpp = format->planes == 1 ? format->bpp / 8 : 1; + + max_pitch = 4095 * bpp; + + if (rcar_du_needs(rcdu, RCAR_DU_QUIRK_ALIGN_128B)) + align = 128; + else + align = 16 * bpp; + } else { + /* +
[PATCH v5 03/10] drm: rcar-du: Move rcar_du_vsp_plane_atomic_update()
Move rcar_du_vsp_plane_atomic_update() to RCar DU vsp lib so that both RCar and RZ/G2L DU vsp drivers can share this function. Signed-off-by: Biju Das --- v5: * New patch --- drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 51 --- drivers/gpu/drm/rcar-du/rcar_du_vsp_lib.c | 51 +++ drivers/gpu/drm/rcar-du/rcar_du_vsp_lib.h | 6 +++ 3 files changed, 57 insertions(+), 51 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c index c9090e581b12..aa63e2d19649 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c @@ -88,42 +88,6 @@ void rcar_du_vsp_enable(struct rcar_du_crtc *crtc) vsp1_du_setup_lif(crtc->vsp->vsp, crtc->vsp_pipe, ); } -static void rcar_du_vsp_plane_setup(struct rcar_du_vsp_plane *plane) -{ - struct rcar_du_vsp_plane_state *state = - to_rcar_vsp_plane_state(plane->plane.state); - struct rcar_du_crtc *crtc = to_rcar_crtc(state->state.crtc); - struct drm_framebuffer *fb = plane->plane.state->fb; - const struct rcar_du_format_info *format; - struct vsp1_du_atomic_config cfg = { - .pixelformat = 0, - .pitch = fb->pitches[0], - .alpha = state->state.alpha >> 8, - .zpos = state->state.zpos, - }; - unsigned int i; - - cfg.src.left = state->state.src.x1 >> 16; - cfg.src.top = state->state.src.y1 >> 16; - cfg.src.width = drm_rect_width(>state.src) >> 16; - cfg.src.height = drm_rect_height(>state.src) >> 16; - - cfg.dst.left = state->state.dst.x1; - cfg.dst.top = state->state.dst.y1; - cfg.dst.width = drm_rect_width(>state.dst); - cfg.dst.height = drm_rect_height(>state.dst); - - for (i = 0; i < state->format->planes; ++i) - cfg.mem[i] = sg_dma_address(state->sg_tables[i].sgl) - + fb->offsets[i]; - - format = rcar_du_format_info(state->format->fourcc); - cfg.pixelformat = format->v4l2; - - vsp1_du_atomic_update(plane->vsp->vsp, crtc->vsp_pipe, - plane->index, ); -} - static int rcar_du_vsp_plane_atomic_check(struct drm_plane *plane, struct drm_atomic_state *state) { @@ -135,21 +99,6 @@ static int rcar_du_vsp_plane_atomic_check(struct drm_plane *plane, >format); } -static void rcar_du_vsp_plane_atomic_update(struct drm_plane *plane, - struct drm_atomic_state *state) -{ - struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, plane); - struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, plane); - struct rcar_du_vsp_plane *rplane = to_rcar_vsp_plane(plane); - struct rcar_du_crtc *crtc = to_rcar_crtc(old_state->crtc); - - if (new_state->visible) - rcar_du_vsp_plane_setup(rplane); - else if (old_state->crtc) - vsp1_du_atomic_update(rplane->vsp->vsp, crtc->vsp_pipe, - rplane->index, NULL); -} - static const struct drm_plane_helper_funcs rcar_du_vsp_plane_helper_funcs = { .prepare_fb = rcar_du_vsp_plane_prepare_fb, .cleanup_fb = rcar_du_vsp_plane_cleanup_fb, diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp_lib.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp_lib.c index 9062837e68da..97f8ac22b582 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_vsp_lib.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp_lib.c @@ -85,6 +85,42 @@ static const u32 rcar_du_vsp_formats[] = { DRM_FORMAT_YVU444, }; +static void rcar_du_vsp_plane_setup(struct rcar_du_vsp_plane *plane) +{ + struct rcar_du_vsp_plane_state *state = + to_rcar_vsp_plane_state(plane->plane.state); + struct rcar_du_crtc *crtc = to_rcar_crtc(state->state.crtc); + struct drm_framebuffer *fb = plane->plane.state->fb; + const struct rcar_du_format_info *format; + struct vsp1_du_atomic_config cfg = { + .pixelformat = 0, + .pitch = fb->pitches[0], + .alpha = state->state.alpha >> 8, + .zpos = state->state.zpos, + }; + unsigned int i; + + cfg.src.left = state->state.src.x1 >> 16; + cfg.src.top = state->state.src.y1 >> 16; + cfg.src.width = drm_rect_width(>state.src) >> 16; + cfg.src.height = drm_rect_height(>state.src) >> 16; + + cfg.dst.left = state->state.dst.x1; + cfg.dst.top = state->state.dst.y1; + cfg.dst.width = drm_rect_width(>state.dst); + cfg.dst.height = drm_rect_height(>state.dst); + + for (i = 0; i < state->format->planes; ++i) + cfg.mem[i] = sg_dma_address(state->sg_tables[i].sgl) + + fb->offsets[i]; + + format = rcar_du_format_info(state->format->fourcc); + cfg.pixelformat =
[PATCH v5 02/10] drm: rcar-du: Move rcar_du_vsp_plane_cleanup_fb()
Move rcar_du_vsp_plane_cleanup_fb() to RCar DU vsp lib so that it can be shared by both RCar and RZ/G2L DU vsp drivers. Signed-off-by: Biju Das --- v5: * New patch --- drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 12 drivers/gpu/drm/rcar-du/rcar_du_vsp_lib.c | 12 drivers/gpu/drm/rcar-du/rcar_du_vsp_lib.h | 6 ++ 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c index 72128915a2ff..c9090e581b12 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c @@ -124,18 +124,6 @@ static void rcar_du_vsp_plane_setup(struct rcar_du_vsp_plane *plane) plane->index, ); } -static void rcar_du_vsp_plane_cleanup_fb(struct drm_plane *plane, -struct drm_plane_state *state) -{ - struct rcar_du_vsp_plane_state *rstate = to_rcar_vsp_plane_state(state); - struct rcar_du_vsp *vsp = to_rcar_vsp_plane(plane)->vsp; - - if (!state->visible) - return; - - rcar_du_vsp_unmap_fb(vsp, state->fb, rstate->sg_tables); -} - static int rcar_du_vsp_plane_atomic_check(struct drm_plane *plane, struct drm_atomic_state *state) { diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp_lib.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp_lib.c index 40d44bf521c0..9062837e68da 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_vsp_lib.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp_lib.c @@ -181,6 +181,18 @@ void rcar_du_vsp_unmap_fb(struct rcar_du_vsp *vsp, struct drm_framebuffer *fb, } } +void rcar_du_vsp_plane_cleanup_fb(struct drm_plane *plane, + struct drm_plane_state *state) +{ + struct rcar_du_vsp_plane_state *rstate = to_rcar_vsp_plane_state(state); + struct rcar_du_vsp *vsp = to_rcar_vsp_plane(plane)->vsp; + + if (!state->visible) + return; + + rcar_du_vsp_unmap_fb(vsp, state->fb, rstate->sg_tables); +} + static struct drm_plane_state * rcar_du_vsp_plane_atomic_duplicate_state(struct drm_plane *plane) { diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp_lib.h b/drivers/gpu/drm/rcar-du/rcar_du_vsp_lib.h index d79cdf7d7316..094ada022fe5 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_vsp_lib.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp_lib.h @@ -68,6 +68,8 @@ int rcar_du_lib_vsp_init(struct rcar_du_vsp *vsp, struct device_node *np, const struct drm_plane_helper_funcs *rcar_du_vsp_plane_helper_funcs); int rcar_du_vsp_plane_prepare_fb(struct drm_plane *plane, struct drm_plane_state *state); +void rcar_du_vsp_plane_cleanup_fb(struct drm_plane *plane, + struct drm_plane_state *state); #else static inline void rcar_du_vsp_disable(struct rcar_du_crtc *crtc) { }; static inline void rcar_du_vsp_atomic_begin(struct rcar_du_crtc *crtc) { }; @@ -95,6 +97,10 @@ static inline int rcar_du_vsp_plane_prepare_fb(struct drm_plane *plane, { return -ENXIO; } +static inline void rcar_du_vsp_plane_cleanup_fb(struct drm_plane *plane, + struct drm_plane_state *state) +{ +} #endif #endif /* __RCAR_DU_VSP_LIB_H__ */ -- 2.25.1
[PATCH v5 00/10] Add RZ/G2L Display support
RZ/G2L LCD controller composed of Frame compression Processor(FCPVD), Video signal processor (VSPD) and Display unit(DU). The output of LCDC is connected to Display parallel interface and MIPI link video interface. This patch series aims to add basic display support on RZ/G2L SMARC EVK platform. The output from DSI is connected to ADV7535. The DU controller is similar to R-Car as it is connected to VSPD, so most of code is based on R-Car with new CRTC/DRM driver specific to RZ/G2L. Basic RCar DU lib created for kms, vsp and encoder drivers[1]. This patch series enhances the RCar DU libs and RZ/G2L started using this libs and there by code size is reduced to almost 50%. Further enhancement possible by sharing common code for DRM and CRTC. Note:- This patch series depend upon [1] [1] https://lore.kernel.org/dri-devel/20220726164208.1048444-1-biju.das...@bp.renesas.com/T/#t v4->v5: * Added Rb tag from Rob for binding patch. * Started using RCar DU libs(kms, vsp and encoder) * Started using rcar_du_device, rcar_du_write, rcar_du_crtc, rcar_du_format_info and rcar_du_encoder. v3->v4: * Changed compatible name from renesas,du-r9a07g044->renesas,r9a07g044-du * started using same compatible for RZ/G2{L,LC} * Removed rzg2l_du_group.h and struct rzg2l_du_group * Renamed __rzg2l_du_group_start_stop->rzg2l_du_start_stop * Removed rzg2l_du_group_restart * Updated rzg2l_du_crtc_set_display_timing * Removed mode_valid callback. * Updated rzg2l_du_crtc_create() parameters * Updated compatible * Removed RZG2L_DU_MAX_GROUPS V2->v3: * Added new bindings for RZ/G2L DU * Removed indirection and created new DRM driver based on R-Car DU v1->v2: * Based on [1], all references to 'rzg2l_lcdc' replaced with 'rzg2l_du' * Updated commit description for bindings * Removed LCDC references from bindings * Changed clock name from du.0->aclk from bindings * Changed reset name from du.0->du from bindings * Replaced crtc_helper_funcs->rcar_crtc_helper_funcs * Updated macro DRM_RZG2L_LCDC->DRM_RZG2L_DU * Replaced rzg2l-lcdc-drm->rzg2l-du-drm * Added forward declaration for struct reset_control [1] https://patchwork.kernel.org/project/linux-renesas-soc/patch/20220312084205.31462-2-biju.das...@bp.renesas.com/ RFC->v1: * Changed minItems->maxItems for renesas,vsps. * Added RZ/G2L LCDC driver with special handling for CRTC reusing most of RCar DU code * Fixed the comments for num_rpf from rpf's->RPFs/ and vsp->VSP. RFC: https://patchwork.kernel.org/project/linux-renesas-soc/patch/20220112174612.10773-18-biju.das...@bp.renesas.com/ https://patchwork.kernel.org/project/linux-renesas-soc/patch/20220112174612.10773-12-biju.das...@bp.renesas.com/ https://patchwork.kernel.org/project/linux-renesas-soc/patch/20220112174612.10773-13-biju.das...@bp.renesas.com/ https://patchwork.kernel.org/project/linux-renesas-soc/patch/20220112174612.10773-19-biju.das...@bp.renesas.com/ Modetest output:- root@smarc-rzg2l:~# modetest -M rzg2l-du Encoders: id crtctypepossible crtcs possible clones 41 40 none0x0001 0x0001 43 0 Virtual 0x0001 0x0002 Connectors: id encoder status namesize (mm) modes encoders 42 41 connected HDMI-A-1520x320 29 41 modes: index name refresh (Hz) hdisp hss hse htot vdisp vss vse vtot) #0 1920x1080 59.72 1920 1968 2000 2080 1080 1082 1087 138000 flags: phsync, nvsync; type: preferred, driver #1 1920x1080 60.00 1920 2008 2052 2200 1080 1084 1089 1125 148500 flags: phsync, pvsync; type: driver #2 1920x1080 59.94 1920 2008 2052 2200 1080 1084 1089 1125 148352 flags: phsync, pvsync; type: driver #3 1920x1080 59.94 1920 2008 2052 2200 1080 1084 1089 1125 148352 flags: phsync, pvsync; type: driver #4 1280x1024 75.02 1280 1296 1440 1688 1024 1025 1028 1066 135000 flags: phsync, pvsync; type: driver #5 1280x1024 60.02 1280 1328 1440 1688 1024 1025 1028 1066 108000 flags: phsync, pvsync; type: driver #6 1152x864 75.00 1152 1216 1344 1600 864 865 868 900 108000 flags: phsync, pvsync; type: driver #7 1280x720 60.00 1280 1390 1430 1650 720 725 730 750 74250 flags: phsync, pvsync; type: driver #8 1280x720 59.94 1280 1390 1430 1650 720 725 730 750 74176 flags: phsync, pvsync; type: driver #9 1280x720 50.00 1280 1720 1760 1980 720 725 730 750 74250 flags: phsync, pvsync; type: driver #10 1280x720 50.00 1280 1720 1760 1980 720 725 730 750 74250 flags: phsync, pvsync; type: driver #11 1024x768 75.03 1024 1040 1136 1312 768 769 772 800 78750 flags: phsync, pvsync; type: driver #12 1024x768 70.07 1024 1048 1184 1328 768 771 777 806 75000 flags: nhsync, nvsync; type: driver #13 1024x768 60.00 1024 1048 1184 1344 768 771 777 806 65000 flags: nhsync, nvsync; type: driver #14 832x624 74.55 832 864 928 1152 624 625 628 667 57284 flags: nhsync, nvsync; type: driver #15 800x600 75.00 800 816 896 1056 600 601 604 625 49500
Re: [PATCH] drm/amdkfd: use time_is_before_jiffies(a + b) to replace "jiffies - a > b"
This patch introduces a build warning for me: CC [M] drivers/gpu/drm/amd/amdgpu/../amdkfd/kfd_interrupt.o In file included from /home/fkuehlin/compute/kernel/include/linux/spinlock.h:54, from /home/fkuehlin/compute/kernel/include/linux/mmzone.h:8, from /home/fkuehlin/compute/kernel/include/linux/gfp.h:6, from /home/fkuehlin/compute/kernel/include/linux/slab.h:15, from /home/fkuehlin/compute/kernel/drivers/gpu/drm/amd/amdgpu/../amdkfd/kfd_interrupt.c:44: /home/fkuehlin/compute/kernel/drivers/gpu/drm/amd/amdgpu/../amdkfd/kfd_interrupt.c: In function ?interrupt_wq?: /home/fkuehlin/compute/kernel/include/linux/typecheck.h:12:18: warning: comparison of distinct pointer types lacks a cast 12 | (void)(&__dummy == &__dummy2); \ | ^~ /home/fkuehlin/compute/kernel/include/linux/jiffies.h:106:3: note: in expansion of macro ?typecheck? 106 | typecheck(unsigned long, b) && \ | ^ /home/fkuehlin/compute/kernel/include/linux/jiffies.h:154:35: note: in expansion of macro ?time_after? 154 | #define time_is_before_jiffies(a) time_after(jiffies, a) | ^~ /home/fkuehlin/compute/kernel/drivers/gpu/drm/amd/amdgpu/../amdkfd/kfd_interrupt.c:159:7: note: in expansion of macro ?time_is_before_jiffies? 159 | if (time_is_before_jiffies(start_jiffies + HZ)) { | ^~ I think you need to change the the definition of start_jiffies to be unsigned long. Do you want to submit a v2 of your patch? That said, I think the existing code was fine, though the type-mismatch highlighted by your patch is a bit iffy. Regards, Felix Am 2022-07-26 um 22:59 schrieb Yu Zhe: time_is_before_jiffies deals with timer wrapping correctly. Signed-off-by: Yu Zhe --- drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c b/drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c index a9466d154395..6397926e059c 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c @@ -156,7 +156,7 @@ static void interrupt_wq(struct work_struct *work) while (dequeue_ih_ring_entry(dev, ih_ring_entry)) { dev->device_info.event_interrupt_class->interrupt_wq(dev, ih_ring_entry); - if (jiffies - start_jiffies > HZ) { + if (time_is_before_jiffies(start_jiffies + HZ)) { /* If we spent more than a second processing signals, * reschedule the worker to avoid soft-lockup warnings */
Re: [PATCH -next] drm/amd/display: remove unneeded semicolon
On 2022-07-26 18:28, Yang Li wrote: Eliminate the following coccicheck warning: ./drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c:2344:67-68: Unneeded semicolon Reported-by: Abaci Robot Signed-off-by: Yang Li --- drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c index 39428488a052..ca44df4fca74 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c @@ -2341,7 +2341,7 @@ void dcn201_populate_dml_writeback_from_context_fpu(struct dc *dc, dout_wb.wb_dst_width = wb_info->dwb_params.dest_width; dout_wb.wb_dst_height = wb_info->dwb_params.dest_height; dout_wb.wb_htaps_luma = wb_info->dwb_params.scaler_taps.h_taps; - dout_wb.wb_vtaps_luma = wb_info->dwb_params.scaler_taps.v_taps;; + dout_wb.wb_vtaps_luma = wb_info->dwb_params.scaler_taps.v_taps; dout_wb.wb_htaps_chroma = wb_info->dwb_params.scaler_taps.h_taps_c; dout_wb.wb_vtaps_chroma = wb_info->dwb_params.scaler_taps.v_taps_c; dout_wb.wb_hratio = wb_info->dwb_params.cnv_params.crop_en ? Reviewed-by: Rodrigo Siqueira And applied to amd-staging-drm-next. Thanks Siqueira
Re: [PATCH v2] drm/ttm: Fix dummy res NULL ptr deref bug
Hi Arunpravin, Às 02:30 de 27/07/22, Arunpravin Paneer Selvam escreveu: > Check the bo->resource value before accessing the resource > mem_type. > > v2: Fix commit description unwrapped warning > > > [ 40.191227][ T184] general protection fault, probably for non-canonical > address 0xdc02: [#1] SMP KASAN PTI > [ 40.192995][ T184] KASAN: null-ptr-deref in range > [0x0010-0x0017] > [ 40.194411][ T184] CPU: 1 PID: 184 Comm: systemd-udevd Not tainted > 5.19.0-rc4-00721-gb297c22b7070 #1 > [ 40.196063][ T184] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), > BIOS 1.16.0-debian-1.16.0-4 04/01/2014 > [ 40.199605][ T184] RIP: 0010:ttm_bo_validate+0x1b3/0x240 [ttm] > [ 40.200754][ T184] Code: e8 72 c5 ff ff 83 f8 b8 74 d4 85 c0 75 54 49 8b > 9e 58 01 00 00 48 b8 00 00 00 00 00 fc ff df 48 8d 7b 10 48 89 fa 48 c1 ea 03 > <0f> b6 04 02 84 c0 74 04 3c 03 7e 44 8b 53 10 31 c0 85 d2 0f 85 58 > [ 40.203685][ T184] RSP: 0018:c96df0c8 EFLAGS: 00010202 > [ 40.204630][ T184] RAX: dc00 RBX: RCX: > 11102f4bb71b > [ 40.205864][ T184] RDX: 0002 RSI: c96df208 RDI: > 0010 > [ 40.207102][ T184] RBP: 192dbe1a R08: c96df208 R09: > > [ 40.208394][ T184] R10: 88817a5f R11: 0001 R12: > c96df110 > [ 40.209692][ T184] R13: c96df0f0 R14: 88817a5db800 R15: > c96df208 > [ 40.210862][ T184] FS: 7f6b1d16e8c0() GS:88839d70() > knlGS: > [ 40.212250][ T184] CS: 0010 DS: ES: CR0: 80050033 > [ 40.213275][ T184] CR2: 55a1001d4ff0 CR3: 0001700f4000 CR4: > 06e0 > [ 40.214469][ T184] Call Trace: > [ 40.214974][ T184] > [ 40.215438][ T184] ? ttm_bo_bounce_temp_buffer+0x140/0x140 [ttm] > [ 40.216572][ T184] ? mutex_spin_on_owner+0x240/0x240 > [ 40.217456][ T184] ? drm_vma_offset_add+0xaa/0x100 [drm] > [ 40.218457][ T184] ttm_bo_init_reserved+0x3d6/0x540 [ttm] > [ 40.219410][ T184] ? shmem_get_inode+0x744/0x980 > [ 40.220231][ T184] ttm_bo_init_validate+0xb1/0x200 [ttm] > [ 40.221172][ T184] ? bo_driver_evict_flags+0x340/0x340 [drm_vram_helper] > [ 40.222530][ T184] ? ttm_bo_init_reserved+0x540/0x540 [ttm] > [ 40.223643][ T184] ? __do_sys_finit_module+0x11a/0x1c0 > [ 40.224654][ T184] ? __shmem_file_setup+0x102/0x280 > [ 40.234764][ T184] drm_gem_vram_create+0x305/0x480 [drm_vram_helper] > [ 40.235766][ T184] ? bo_driver_evict_flags+0x340/0x340 [drm_vram_helper] > [ 40.236846][ T184] ? __kasan_slab_free+0x108/0x180 > [ 40.237650][ T184] drm_gem_vram_fill_create_dumb+0x134/0x340 > [drm_vram_helper] > [ 40.238864][ T184] ? local_pci_probe+0xdf/0x180 > [ 40.239674][ T184] ? drmm_vram_helper_init+0x400/0x400 [drm_vram_helper] > [ 40.240826][ T184] drm_client_framebuffer_create+0x19c/0x400 [drm] > [ 40.241955][ T184] ? drm_client_buffer_delete+0x200/0x200 [drm] > [ 40.243001][ T184] ? drm_client_pick_crtcs+0x554/0xb80 [drm] > [ 40.244030][ T184] drm_fb_helper_generic_probe+0x23f/0x940 > [drm_kms_helper] > [ 40.245226][ T184] ? __cond_resched+0x1c/0xc0 > [ 40.245987][ T184] ? drm_fb_helper_memory_range_to_clip+0x180/0x180 > [drm_kms_helper] > [ 40.247316][ T184] ? mutex_unlock+0x80/0x100 > [ 40.248005][ T184] ? __mutex_unlock_slowpath+0x2c0/0x2c0 > [ 40.249083][ T184] drm_fb_helper_single_fb_probe+0x907/0xf00 > [drm_kms_helper] > [ 40.250314][ T184] ? drm_fb_helper_check_var+0x1180/0x1180 > [drm_kms_helper] > [ 40.251540][ T184] ? __cond_resched+0x1c/0xc0 > [ 40.252321][ T184] ? mutex_lock+0x9f/0x100 > [ 40.253062][ T184] __drm_fb_helper_initial_config_and_unlock+0xb9/0x2c0 > [drm_kms_helper] > [ 40.254394][ T184] drm_fbdev_client_hotplug+0x56f/0x840 [drm_kms_helper] > [ 40.255477][ T184] drm_fbdev_generic_setup+0x165/0x3c0 [drm_kms_helper] > [ 40.256607][ T184] bochs_pci_probe+0x6b7/0x900 [bochs] > [ 40.257515][ T184] ? _raw_spin_lock_irqsave+0x87/0x100 > [ 40.258312][ T184] ? bochs_hw_init+0x480/0x480 [bochs] > [ 40.259244][ T184] ? bochs_hw_init+0x480/0x480 [bochs] > [ 40.260186][ T184] local_pci_probe+0xdf/0x180 > [ 40.260928][ T184] pci_call_probe+0x15f/0x500 > [ 40.265798][ T184] ? _raw_spin_lock+0x81/0x100 > [ 40.266508][ T184] ? pci_pm_suspend_noirq+0x980/0x980 > [ 40.267322][ T184] ? pci_assign_irq+0x81/0x280 > [ 40.268096][ T184] ? pci_match_device+0x351/0x6c0 > [ 40.268883][ T184] ? kernfs_put+0x18/0x40 > [ 40.269611][ T184] pci_device_probe+0xee/0x240 > [ 40.270352][ T184] really_probe+0x435/0xa80 > [ 40.271021][ T184] __driver_probe_device+0x2ab/0x480 > [ 40.271828][ T184] driver_probe_device+0x49/0x140 > [ 40.272627][ T184] __driver_attach+0x1bd/0x4c0 > [ 40.273372][ T184] ? __device_attach_driver+0x240/0x240 >
Re: [PATCH] drm/amdgpu: fix i2s_pdata out of bound array access
On Wed, Jul 27, 2022 at 11:16 AM Mukunda,Vijendar wrote: > > On 7/27/22 8:25 PM, Alex Deucher wrote: > > On Wed, Jul 27, 2022 at 10:42 AM Vijendar Mukunda > > wrote: > >> > >> Fixed following Smatch static checker warning: > >> > >> drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c:393 acp_hw_init() > >> error: buffer overflow 'i2s_pdata' 3 <= 3 > >> drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c:396 acp_hw_init() > >> error: buffer overflow 'i2s_pdata' 3 <= 3 > >> > >> Reported-by: Dan Carpenter > >> Signed-off-by: Vijendar Mukunda > >> --- > >> drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c | 8 > >> 1 file changed, 8 deletions(-) > >> > >> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c > >> b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c > >> index bcc7ee02e0fc..6d72355ac492 100644 > >> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c > >> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c > >> @@ -390,14 +390,6 @@ static int acp_hw_init(void *handle) > >> i2s_pdata[2].i2s_reg_comp1 = ACP_BT_COMP1_REG_OFFSET; > >> i2s_pdata[2].i2s_reg_comp2 = ACP_BT_COMP2_REG_OFFSET; > >> > >> - i2s_pdata[3].quirks = DW_I2S_QUIRK_COMP_REG_OFFSET; > >> - switch (adev->asic_type) { > >> - case CHIP_STONEY: > >> - i2s_pdata[3].quirks |= > >> DW_I2S_QUIRK_16BIT_IDX_OVERRIDE; > >> - break; > >> - default: > >> - break; > >> - } > > > > Is this actually not used or should we just increase the allocation size? > > > > Alex > it's my bad. i2s_pdata array size is 3. when we recently included code > changes for JD platform , this piece of code was added mistakenly for > Stoney platform switch case. Thanks. Patch is: Acked-by: Alex Deucher > > -- > Vijendar > > > > >> adev->acp.acp_res[0].name = "acp2x_dma"; > >> adev->acp.acp_res[0].flags = IORESOURCE_MEM; > >> adev->acp.acp_res[0].start = acp_base; > >> -- > >> 2.25.1 > >> >
Re: [PATCH] drm/amdgpu: fix i2s_pdata out of bound array access
On 7/27/22 8:25 PM, Alex Deucher wrote: > On Wed, Jul 27, 2022 at 10:42 AM Vijendar Mukunda > wrote: >> >> Fixed following Smatch static checker warning: >> >> drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c:393 acp_hw_init() >> error: buffer overflow 'i2s_pdata' 3 <= 3 >> drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c:396 acp_hw_init() >> error: buffer overflow 'i2s_pdata' 3 <= 3 >> >> Reported-by: Dan Carpenter >> Signed-off-by: Vijendar Mukunda >> --- >> drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c | 8 >> 1 file changed, 8 deletions(-) >> >> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c >> b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c >> index bcc7ee02e0fc..6d72355ac492 100644 >> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c >> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c >> @@ -390,14 +390,6 @@ static int acp_hw_init(void *handle) >> i2s_pdata[2].i2s_reg_comp1 = ACP_BT_COMP1_REG_OFFSET; >> i2s_pdata[2].i2s_reg_comp2 = ACP_BT_COMP2_REG_OFFSET; >> >> - i2s_pdata[3].quirks = DW_I2S_QUIRK_COMP_REG_OFFSET; >> - switch (adev->asic_type) { >> - case CHIP_STONEY: >> - i2s_pdata[3].quirks |= >> DW_I2S_QUIRK_16BIT_IDX_OVERRIDE; >> - break; >> - default: >> - break; >> - } > > Is this actually not used or should we just increase the allocation size? > > Alex it's my bad. i2s_pdata array size is 3. when we recently included code changes for JD platform , this piece of code was added mistakenly for Stoney platform switch case. -- Vijendar > >> adev->acp.acp_res[0].name = "acp2x_dma"; >> adev->acp.acp_res[0].flags = IORESOURCE_MEM; >> adev->acp.acp_res[0].start = acp_base; >> -- >> 2.25.1 >>
Re: [PATCH] drm/amdgpu: fix i2s_pdata out of bound array access
On Wed, Jul 27, 2022 at 10:42 AM Vijendar Mukunda wrote: > > Fixed following Smatch static checker warning: > > drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c:393 acp_hw_init() > error: buffer overflow 'i2s_pdata' 3 <= 3 > drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c:396 acp_hw_init() > error: buffer overflow 'i2s_pdata' 3 <= 3 > > Reported-by: Dan Carpenter > Signed-off-by: Vijendar Mukunda > --- > drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c | 8 > 1 file changed, 8 deletions(-) > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c > b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c > index bcc7ee02e0fc..6d72355ac492 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c > @@ -390,14 +390,6 @@ static int acp_hw_init(void *handle) > i2s_pdata[2].i2s_reg_comp1 = ACP_BT_COMP1_REG_OFFSET; > i2s_pdata[2].i2s_reg_comp2 = ACP_BT_COMP2_REG_OFFSET; > > - i2s_pdata[3].quirks = DW_I2S_QUIRK_COMP_REG_OFFSET; > - switch (adev->asic_type) { > - case CHIP_STONEY: > - i2s_pdata[3].quirks |= > DW_I2S_QUIRK_16BIT_IDX_OVERRIDE; > - break; > - default: > - break; > - } Is this actually not used or should we just increase the allocation size? Alex > adev->acp.acp_res[0].name = "acp2x_dma"; > adev->acp.acp_res[0].flags = IORESOURCE_MEM; > adev->acp.acp_res[0].start = acp_base; > -- > 2.25.1 >
[PATCH] drm/amdgpu: fix i2s_pdata out of bound array access
Fixed following Smatch static checker warning: drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c:393 acp_hw_init() error: buffer overflow 'i2s_pdata' 3 <= 3 drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c:396 acp_hw_init() error: buffer overflow 'i2s_pdata' 3 <= 3 Reported-by: Dan Carpenter Signed-off-by: Vijendar Mukunda --- drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c | 8 1 file changed, 8 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c index bcc7ee02e0fc..6d72355ac492 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c @@ -390,14 +390,6 @@ static int acp_hw_init(void *handle) i2s_pdata[2].i2s_reg_comp1 = ACP_BT_COMP1_REG_OFFSET; i2s_pdata[2].i2s_reg_comp2 = ACP_BT_COMP2_REG_OFFSET; - i2s_pdata[3].quirks = DW_I2S_QUIRK_COMP_REG_OFFSET; - switch (adev->asic_type) { - case CHIP_STONEY: - i2s_pdata[3].quirks |= DW_I2S_QUIRK_16BIT_IDX_OVERRIDE; - break; - default: - break; - } adev->acp.acp_res[0].name = "acp2x_dma"; adev->acp.acp_res[0].flags = IORESOURCE_MEM; adev->acp.acp_res[0].start = acp_base; -- 2.25.1
Re: [PATCH v3 5/6] drm/i915/gt: Batch TLB invalidations
Hi Mauro, I think there are still some unanswered questions from Tvrtko on this patch, am I right? Andi On Wed, Jul 27, 2022 at 02:29:55PM +0200, Mauro Carvalho Chehab wrote: > From: Chris Wilson > > Invalidate TLB in batches, in order to reduce performance regressions. > > Currently, every caller performs a full barrier around a TLB > invalidation, ignoring all other invalidations that may have already > removed their PTEs from the cache. As this is a synchronous operation > and can be quite slow, we cause multiple threads to contend on the TLB > invalidate mutex blocking userspace. > > We only need to invalidate the TLB once after replacing our PTE to > ensure that there is no possible continued access to the physical > address before releasing our pages. By tracking a seqno for each full > TLB invalidate we can quickly determine if one has been performed since > rewriting the PTE, and only if necessary trigger one for ourselves. > > That helps to reduce the performance regression introduced by TLB > invalidate logic. > > [mchehab: rebased to not require moving the code to a separate file] > > Cc: sta...@vger.kernel.org > Fixes: 7938d61591d3 ("drm/i915: Flush TLBs before releasing backing store") > Suggested-by: Tvrtko Ursulin > Signed-off-by: Chris Wilson > Cc: Fei Yang > Signed-off-by: Mauro Carvalho Chehab > --- > > To avoid mailbombing on a large number of people, only mailing lists were C/C > on the cover. > See [PATCH v3 0/6] at: > https://lore.kernel.org/all/cover.1658924372.git.mche...@kernel.org/ > > .../gpu/drm/i915/gem/i915_gem_object_types.h | 3 +- > drivers/gpu/drm/i915/gem/i915_gem_pages.c | 21 +--- > drivers/gpu/drm/i915/gt/intel_gt.c| 53 ++- > drivers/gpu/drm/i915/gt/intel_gt.h| 12 - > drivers/gpu/drm/i915/gt/intel_gt_types.h | 18 ++- > drivers/gpu/drm/i915/gt/intel_ppgtt.c | 8 ++- > drivers/gpu/drm/i915/i915_vma.c | 33 +--- > drivers/gpu/drm/i915/i915_vma.h | 1 + > drivers/gpu/drm/i915/i915_vma_resource.c | 5 +- > drivers/gpu/drm/i915/i915_vma_resource.h | 6 ++- > 10 files changed, 125 insertions(+), 35 deletions(-) > > diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h > b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h > index 5cf36a130061..9f6b14ec189a 100644 > --- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h > +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h > @@ -335,7 +335,6 @@ struct drm_i915_gem_object { > #define I915_BO_READONLY BIT(7) > #define I915_TILING_QUIRK_BIT 8 /* unknown swizzling; do not release! */ > #define I915_BO_PROTECTED BIT(9) > -#define I915_BO_WAS_BOUND_BIT 10 > /** >* @mem_flags - Mutable placement-related flags >* > @@ -616,6 +615,8 @@ struct drm_i915_gem_object { >* pages were last acquired. >*/ > bool dirty:1; > + > + u32 tlb; > } mm; > > struct { > diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pages.c > b/drivers/gpu/drm/i915/gem/i915_gem_pages.c > index 6835279943df..8357dbdcab5c 100644 > --- a/drivers/gpu/drm/i915/gem/i915_gem_pages.c > +++ b/drivers/gpu/drm/i915/gem/i915_gem_pages.c > @@ -191,6 +191,18 @@ static void unmap_object(struct drm_i915_gem_object > *obj, void *ptr) > vunmap(ptr); > } > > +static void flush_tlb_invalidate(struct drm_i915_gem_object *obj) > +{ > + struct drm_i915_private *i915 = to_i915(obj->base.dev); > + struct intel_gt *gt = to_gt(i915); > + > + if (!obj->mm.tlb) > + return; > + > + intel_gt_invalidate_tlb(gt, obj->mm.tlb); > + obj->mm.tlb = 0; > +} > + > struct sg_table * > __i915_gem_object_unset_pages(struct drm_i915_gem_object *obj) > { > @@ -216,14 +228,7 @@ __i915_gem_object_unset_pages(struct drm_i915_gem_object > *obj) > __i915_gem_object_reset_page_iter(obj); > obj->mm.page_sizes.phys = obj->mm.page_sizes.sg = 0; > > - if (test_and_clear_bit(I915_BO_WAS_BOUND_BIT, >flags)) { > - struct drm_i915_private *i915 = to_i915(obj->base.dev); > - struct intel_gt *gt = to_gt(i915); > - intel_wakeref_t wakeref; > - > - with_intel_gt_pm_if_awake(gt, wakeref) > - intel_gt_invalidate_tlbs(gt); > - } > + flush_tlb_invalidate(obj); > > return pages; > } > diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c > b/drivers/gpu/drm/i915/gt/intel_gt.c > index 5c55a90672f4..f435e06125aa 100644 > --- a/drivers/gpu/drm/i915/gt/intel_gt.c > +++ b/drivers/gpu/drm/i915/gt/intel_gt.c > @@ -38,8 +38,6 @@ static void __intel_gt_init_early(struct intel_gt *gt) > { > spin_lock_init(>irq_lock); > > - mutex_init(>tlb_invalidate_lock); > - > INIT_LIST_HEAD(>closed_vma); > spin_lock_init(>closed_lock); > > @@ -50,6 +48,8 @@ static void __intel_gt_init_early(struct intel_gt *gt) >
Re: [Intel-gfx] [PATCH v3 6/6] drm/i915/gt: describe the new tlb parameter at i915_vma_resource
Hi Mauro, > TLB cache invalidation can happen on two different situations: > > 1. synchronously, at __vma_put_pages(); > 2. asynchronously. > > On the first case, TLB cache invalidation happens inside > __vma_put_pages(). So, no need to do it later on. > > However, on the second case, the pages will keep in memory > until __i915_vma_evict() is called. > > So, we need to store the TLB data at struct i915_vma_resource, > in order to do a TLB cache invalidation before allowing > userspace to re-use the same memory. > > So, i915_vma_resource_unbind() has gained a new parameter > in order to store the TLB data at the second case. > > Document it. > > Signed-off-by: Mauro Carvalho Chehab > --- > > To avoid mailbombing on a large number of people, only mailing lists were C/C > on the cover. > See [PATCH v3 0/6] at: > https://lore.kernel.org/all/cover.1658924372.git.mche...@kernel.org/ > > drivers/gpu/drm/i915/i915_vma_resource.c | 4 > 1 file changed, 4 insertions(+) > > diff --git a/drivers/gpu/drm/i915/i915_vma_resource.c > b/drivers/gpu/drm/i915/i915_vma_resource.c > index 5a67995ea5fe..4fe09ea0a825 100644 > --- a/drivers/gpu/drm/i915/i915_vma_resource.c > +++ b/drivers/gpu/drm/i915/i915_vma_resource.c > @@ -216,6 +216,10 @@ i915_vma_resource_fence_notify(struct i915_sw_fence > *fence, > /** > * i915_vma_resource_unbind - Unbind a vma resource > * @vma_res: The vma resource to unbind. > + * @tlb: pointer to vma->obj->mm.tlb associated with the resource > + *to be stored at vma_res->tlb. When not-NULL, it will be used > + *to do TLB cache invalidation before freeing a VMA resource. > + *used only for async unbind. /used/Used/ With that: Reviewed-by: Andi Shyti Thanks, Andi
Re: [Intel-gfx] [PATCH v3 2/6] drm/i915/gt: document with_intel_gt_pm_if_awake()
Hi Mauro, > Add a kernel-doc markup to document this new macro. > > Reviewed-by: Tvrtko Ursulin > Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Andi Shyti Andi
Re: [Freedreno] [PATCH] drm/msm/dsi: Don't set a load before disabling a regulator
Hi, On Wed, Jul 27, 2022 at 6:59 AM Dmitry Baryshkov wrote: > > On Wed, 27 Jul 2022 at 16:57, Doug Anderson wrote: > > > > Hi, > > > > On Tue, Jul 26, 2022 at 4:53 PM Abhinav Kumar > > wrote: > > > > > > On 7/25/2022 5:49 PM, Douglas Anderson wrote: > > > > As of commit 5451781dadf8 ("regulator: core: Only count load for > > > > enabled consumers"), a load isn't counted for a disabled > > > > regulator. That means all the code in the DSI driver to specify and > > > > set loads before disabling a regulator is not actually doing anything > > > > useful. Let's remove it. > > > > > > > > It should be noted that all of the loads set that were being specified > > > > were pointless noise anyway. The only use for this number is to pick > > > > between low power and high power modes of regulators. Regulators > > > > appear to do this changeover at loads on the order of 1 uA. You > > > > would a lot of clients of the same rail for that 100 uA number to > > > > > > I guess you meant "you would need a lot of clients" > > > > Yeah, sorry. :( I'll fix it up if I need a v3. > > > > > > > > @@ -259,15 +259,7 @@ static inline struct msm_dsi_host > > > > *to_msm_dsi_host(struct mipi_dsi_host *host) > > > > static void dsi_host_regulator_disable(struct msm_dsi_host *msm_host) > > > > { > > > It seems like now we can drop this function dsi_host_regulator_disable() > > > entirely and just call regulator_bulk_disable() ? > > > > Sure, if you want. One could still argue that it provides a tiny bit > > of abstraction and avoids the caller from having to know where to find > > the number of regulators and all that, but I can go either way. Is > > this worth a v3, do you think? If so, I might tack it on at the end of > > the series. > > I'd say, drop it. Having extra single-call wrappers doesn't seem to add a lot. Sounds good. I'll wait a little bit of time for feedback on the larger series and then send a v3, probably next week. -Doug
Re: [Freedreno] [PATCH] drm/msm/dsi: Don't set a load before disabling a regulator
Hi, On Tue, Jul 26, 2022 at 4:53 PM Abhinav Kumar wrote: > > On 7/25/2022 5:49 PM, Douglas Anderson wrote: > > As of commit 5451781dadf8 ("regulator: core: Only count load for > > enabled consumers"), a load isn't counted for a disabled > > regulator. That means all the code in the DSI driver to specify and > > set loads before disabling a regulator is not actually doing anything > > useful. Let's remove it. > > > > It should be noted that all of the loads set that were being specified > > were pointless noise anyway. The only use for this number is to pick > > between low power and high power modes of regulators. Regulators > > appear to do this changeover at loads on the order of 1 uA. You > > would a lot of clients of the same rail for that 100 uA number to > > I guess you meant "you would need a lot of clients" Yeah, sorry. :( I'll fix it up if I need a v3. > > @@ -259,15 +259,7 @@ static inline struct msm_dsi_host > > *to_msm_dsi_host(struct mipi_dsi_host *host) > > static void dsi_host_regulator_disable(struct msm_dsi_host *msm_host) > > { > It seems like now we can drop this function dsi_host_regulator_disable() > entirely and just call regulator_bulk_disable() ? Sure, if you want. One could still argue that it provides a tiny bit of abstraction and avoids the caller from having to know where to find the number of regulators and all that, but I can go either way. Is this worth a v3, do you think? If so, I might tack it on at the end of the series. Note that I say "v3" because I actually included this patch in a larger series and called that series "v2" [1]. [1] https://lore.kernel.org/r/20220726173824.1166873-1-diand...@chromium.org
Re: [Freedreno] [PATCH] drm/msm/dsi: Don't set a load before disabling a regulator
On Wed, 27 Jul 2022 at 16:57, Doug Anderson wrote: > > Hi, > > On Tue, Jul 26, 2022 at 4:53 PM Abhinav Kumar > wrote: > > > > On 7/25/2022 5:49 PM, Douglas Anderson wrote: > > > As of commit 5451781dadf8 ("regulator: core: Only count load for > > > enabled consumers"), a load isn't counted for a disabled > > > regulator. That means all the code in the DSI driver to specify and > > > set loads before disabling a regulator is not actually doing anything > > > useful. Let's remove it. > > > > > > It should be noted that all of the loads set that were being specified > > > were pointless noise anyway. The only use for this number is to pick > > > between low power and high power modes of regulators. Regulators > > > appear to do this changeover at loads on the order of 1 uA. You > > > would a lot of clients of the same rail for that 100 uA number to > > > > I guess you meant "you would need a lot of clients" > > Yeah, sorry. :( I'll fix it up if I need a v3. > > > > > @@ -259,15 +259,7 @@ static inline struct msm_dsi_host > > > *to_msm_dsi_host(struct mipi_dsi_host *host) > > > static void dsi_host_regulator_disable(struct msm_dsi_host *msm_host) > > > { > > It seems like now we can drop this function dsi_host_regulator_disable() > > entirely and just call regulator_bulk_disable() ? > > Sure, if you want. One could still argue that it provides a tiny bit > of abstraction and avoids the caller from having to know where to find > the number of regulators and all that, but I can go either way. Is > this worth a v3, do you think? If so, I might tack it on at the end of > the series. I'd say, drop it. Having extra single-call wrappers doesn't seem to add a lot. > > Note that I say "v3" because I actually included this patch in a > larger series and called that series "v2" [1]. > > > [1] https://lore.kernel.org/r/20220726173824.1166873-1-diand...@chromium.org -- With best wishes Dmitry
Re: [PATCH] drm: Fix EDID firmware load on resume
Hi, Caching the EDID via the firmware API makes the kernel able to reclaim the memory in case it's needed. And eventually, the kernel will load it again before suspending. But for 128 bytes, even if we have many monitors it will not make any difference. I don't know if storing a platform device can take more memory than 128 bytes of data. I let you decide which option is better. Just tell me if I should cache the bytes instead. Thanks. Matthieu On Wed, Jul 27 2022 at 10:18:48 AM +0200, Takashi Iwai wrote: On Wed, 27 Jul 2022 09:41:52 +0200, Matthieu CHARETTE wrote: Loading an EDID using drm.edid_firmware parameter makes resume to fail after firmware cache is being cleaned. This is because edid_load() use a temporary device to request the firmware. This cause the EDID firmware not to be cached from suspend. And, requesting the EDID firmware return an error during resume. So the request_firmware() call should use a permanent device for each connector. Also, we should cache the EDID even if no monitor is connected, in case it's plugged while suspended. Link: https://gitlab.freedesktop.org/drm/amd/-/issues/2061 Signed-off-by: Matthieu CHARETTE Can we simply cache the already loaded EDID bytes instead? Something like below (totally untested). thanks, Takashi -- 8< -- diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 1c48d162c77e..b9d2803b518b 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -286,6 +286,7 @@ int drm_connector_init(struct drm_device *dev, connector->status = connector_status_unknown; connector->display_info.panel_orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN; + connector->firmware_edid = NULL; drm_connector_get_cmdline_mode(connector); @@ -485,6 +486,7 @@ void drm_connector_cleanup(struct drm_connector *connector) ida_simple_remove(>mode_config.connector_ida, connector->index); + kfree(connector->firmware_edid); kfree(connector->display_info.bus_formats); drm_mode_object_unregister(dev, >base); kfree(connector->name); diff --git a/drivers/gpu/drm/drm_edid_load.c b/drivers/gpu/drm/drm_edid_load.c index 37d8ba3ddb46..a38fe4e00e4a 100644 --- a/drivers/gpu/drm/drm_edid_load.c +++ b/drivers/gpu/drm/drm_edid_load.c @@ -253,6 +253,13 @@ static void *edid_load(struct drm_connector *connector, const char *name, edid = new_edid; } + connector->firmware_edid = drm_edid_duplicate((struct edid *)edid); + if (!connector->firmware_edid) { + kfree(edid); + edid = ERR_PTR(-ENOMEM); + goto out; + } + DRM_INFO("Got %s EDID base block and %d extension%s from " "\"%s\" for connector \"%s\"\n", (builtin >= 0) ? "built-in" : "external", valid_extensions, valid_extensions == 1 ? "" : "s", @@ -269,6 +276,12 @@ struct edid *drm_load_edid_firmware(struct drm_connector *connector) char *edidname, *last, *colon, *fwstr, *edidstr, *fallback = NULL; struct edid *edid; + /* already loaded? */ + if (connector->firmware_edid) { + edid = drm_edid_duplicate(connector->firmware_edid); + return edid ? edid : ERR_PTR(-ENOMEM); + } + if (edid_firmware[0] == '\0') return ERR_PTR(-ENOENT); diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 3ac4bf87f257..b5d0c87327a3 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -1528,6 +1528,8 @@ struct drm_connector { enum drm_connector_force force; /** @override_edid: has the EDID been overwritten through debugfs for testing? */ bool override_edid; + /** @firmware_edid: the cached firmware EDID bytes */ + struct edid *firmware_edid; /** @epoch_counter: used to detect any other changes in connector, besides status */ u64 epoch_counter;
[drm:drm-next 6/19] drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c:676:1: sparse: sparse: symbol 'gv100_disp_core_mthd_base' was not declared. Should it be static?
tree: git://anongit.freedesktop.org/drm/drm drm-next head: 2bc7ea71a73747a77e7f83bc085b0d2393235410 commit: acbe9ecfb7fb14db868ddbeda8f43e623026316b [6/19] drm/nouveau/disp: merge head/outp/ior code into chipset files config: alpha-randconfig-s032-20220725 compiler: alpha-linux-gcc (GCC) 12.1.0 reproduce: wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # apt-get install sparse # sparse version: v0.6.4-39-gce1a6720-dirty git remote add drm git://anongit.freedesktop.org/drm/drm git fetch --no-tags drm drm-next git checkout acbe9ecfb7fb14db868ddbeda8f43e623026316b # save the config file mkdir build_dir && cp config build_dir/.config COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=alpha SHELL=/bin/bash drivers/gpu/drm/ If you fix the issue, kindly add following tag where applicable Reported-by: kernel test robot sparse warnings: (new ones prefixed by >>) >> drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c:676:1: sparse: sparse: >> symbol 'gv100_disp_core_mthd_base' was not declared. Should it be static? vim +/gv100_disp_core_mthd_base +676 drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c 674 675 const struct nvkm_disp_mthd_list > 676 gv100_disp_core_mthd_base = { 677 .mthd = 0x, 678 .addr = 0x00, 679 .data = { 680 { 0x0200, 0x680200 }, 681 { 0x0208, 0x680208 }, 682 { 0x020c, 0x68020c }, 683 { 0x0210, 0x680210 }, 684 { 0x0214, 0x680214 }, 685 { 0x0218, 0x680218 }, 686 { 0x021c, 0x68021c }, 687 {} 688 } 689 }; 690 -- 0-DAY CI Kernel Test Service https://01.org/lkp # # Automatically generated file; DO NOT EDIT. # Linux/alpha 5.19.0-rc6 Kernel Configuration # CONFIG_CC_VERSION_TEXT="alpha-linux-gcc (GCC) 12.1.0" CONFIG_CC_IS_GCC=y CONFIG_GCC_VERSION=120100 CONFIG_CLANG_VERSION=0 CONFIG_AS_IS_GNU=y CONFIG_AS_VERSION=23800 CONFIG_LD_IS_BFD=y CONFIG_LD_VERSION=23800 CONFIG_LLD_VERSION=0 CONFIG_CC_HAS_ASM_GOTO=y CONFIG_CC_HAS_ASM_INLINE=y CONFIG_CC_HAS_NO_PROFILE_FN_ATTR=y CONFIG_PAHOLE_VERSION=123 CONFIG_CONSTRUCTORS=y CONFIG_IRQ_WORK=y # # General setup # CONFIG_BROKEN_ON_SMP=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_COMPILE_TEST=y # CONFIG_WERROR is not set CONFIG_LOCALVERSION="" CONFIG_BUILD_SALT="" CONFIG_DEFAULT_INIT="" CONFIG_DEFAULT_HOSTNAME="(none)" # CONFIG_SYSVIPC is not set CONFIG_WATCH_QUEUE=y CONFIG_CROSS_MEMORY_ATTACH=y # CONFIG_USELIB is not set CONFIG_HAVE_ARCH_AUDITSYSCALL=y # # IRQ subsystem # CONFIG_GENERIC_IRQ_PROBE=y CONFIG_GENERIC_IRQ_SHOW=y CONFIG_IRQ_DOMAIN=y CONFIG_IRQ_SIM=y CONFIG_IRQ_DOMAIN_HIERARCHY=y # CONFIG_GENERIC_IRQ_DEBUGFS is not set # end of IRQ subsystem CONFIG_GENERIC_CLOCKEVENTS=y CONFIG_TIME_KUNIT_TEST=y # # Timers subsystem # CONFIG_TICK_ONESHOT=y CONFIG_HZ_PERIODIC=y # CONFIG_NO_HZ_IDLE is not set # CONFIG_NO_HZ is not set CONFIG_HIGH_RES_TIMERS=y # end of Timers subsystem CONFIG_BPF=y # # BPF subsystem # CONFIG_BPF_SYSCALL=y # CONFIG_BPF_UNPRIV_DEFAULT_OFF is not set # end of BPF subsystem CONFIG_PREEMPT_NONE_BUILD=y CONFIG_PREEMPT_NONE=y # # CPU/Task time and stats accounting # CONFIG_TICK_CPU_ACCOUNTING=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_PSI=y CONFIG_PSI_DEFAULT_DISABLED=y # end of CPU/Task time and stats accounting CONFIG_CPU_ISOLATION=y # # RCU Subsystem # CONFIG_TINY_RCU=y # CONFIG_RCU_EXPERT is not set CONFIG_SRCU=y CONFIG_TINY_SRCU=y CONFIG_TASKS_RCU_GENERIC=y CONFIG_TASKS_TRACE_RCU=y CONFIG_RCU_NEED_SEGCBLIST=y # end of RCU Subsystem CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_IKHEADERS=y # # Scheduler features # # end of Scheduler features CONFIG_CC_HAS_INT128=y CONFIG_CC_IMPLICIT_FALLTHROUGH="-Wimplicit-fallthrough=5" CONFIG_GCC12_NO_ARRAY_BOUNDS=y CONFIG_CC_NO_ARRAY_BOUNDS=y # CONFIG_CGROUPS is not set # CONFIG_NAMESPACES is not set CONFIG_CHECKPOINT_RESTORE=y # CONFIG_SCHED_AUTOGROUP is not set # CONFIG_SYSFS_DEPRECATED is not set # CONFIG_RELAY is not set CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" CONFIG_RD_GZIP=y # CONFIG_RD_BZIP2 is not set # CONFIG_RD_LZMA is not set CONFIG_RD_XZ=y # CONFIG_RD_LZO is not set # CONFIG_RD_LZ4 is not set # CONFIG_RD_ZSTD is not set # CONFIG_BOOT_CONFIG is not set CONFIG_INITRAMFS_PRESERVE_MTIME=y CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_SYSCTL=y CONFIG_HAVE_PCSPKR_PLATFORM=y CONFIG_EXPERT=y CONFIG_MULTIUSER=y CONFIG_SGETMASK_SYSCALL=y CONFIG_SYSFS_SYSCALL=y # CONFIG_FHANDLE is not set # CONFIG_POSIX_TIMERS is not set # CONFIG_PRINTK is not set CONFIG_BUG=y CONFIG_PCSPKR_PLATFORM=y # CONFIG_BASE_FULL is not set # CONFIG_FUTEX is not set CONFIG_EPOLL=y # CONFIG_SIGNALFD is
Re: [PATCH 8/8] drm/tidss: Enable Dual and Duplicate Modes for OLDI
Hi, On 19/07/2022 11:08, Aradhya Bhatia wrote: The AM625 DSS peripheral supports 2 OLDI TXes which can work to enable 2 duplicated displays of smaller resolutions or enable a single Dual-Link display with a higher resolution (1920x1200). Configure the necessary register to enable the different modes. Signed-off-by: Aradhya Bhatia --- drivers/gpu/drm/tidss/tidss_dispc.c | 44 +++-- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/tidss/tidss_dispc.c b/drivers/gpu/drm/tidss/tidss_dispc.c index 0b9689453ee8..28cb61259471 100644 --- a/drivers/gpu/drm/tidss/tidss_dispc.c +++ b/drivers/gpu/drm/tidss/tidss_dispc.c @@ -1021,8 +1021,8 @@ static void dispc_enable_oldi(struct dispc_device *dispc, u32 hw_videoport, int count = 0; /* -* For the moment DUALMODESYNC, MASTERSLAVE, MODE, and SRC -* bits of DISPC_VP_DSS_OLDI_CFG are set statically to 0. +* For the moment MASTERSLAVE, and SRC bits of DISPC_VP_DSS_OLDI_CFG are +* set statically to 0. */ if (fmt->data_width == 24) @@ -1039,7 +1039,45 @@ static void dispc_enable_oldi(struct dispc_device *dispc, u32 hw_videoport, oldi_cfg |= BIT(0); /* ENABLE */ - dispc_vp_write(dispc, hw_videoport, DISPC_VP_DSS_OLDI_CFG, oldi_cfg); + /* +* As per all the current implementations of DSS, the OLDI TXes are present only on +* hw_videoport = 0 (OLDI TX 0). However, the config register for 2nd OLDI TX (OLDI TX 1) +* is present in the address space of hw_videoport = 1. Hence, using "hw_videoport + 1" to +* configure OLDI TX 1. +*/ + + switch (dispc->oldi_mode) { + case OLDI_MODE_OFF: + oldi_cfg &= ~BIT(0); /* DISABLE */ + dispc_vp_write(dispc, hw_videoport, DISPC_VP_DSS_OLDI_CFG, oldi_cfg); + dispc_vp_write(dispc, hw_videoport + 1, DISPC_VP_DSS_OLDI_CFG, oldi_cfg); + break; + + case OLDI_SINGLE_LINK_SINGLE_MODE_0: + dispc_vp_write(dispc, hw_videoport, DISPC_VP_DSS_OLDI_CFG, oldi_cfg); + break; + + case OLDI_SINGLE_LINK_SINGLE_MODE_1: + dispc_vp_write(dispc, hw_videoport + 1, DISPC_VP_DSS_OLDI_CFG, oldi_cfg); + break; + + case OLDI_SINGLE_LINK_DUPLICATE_MODE: + oldi_cfg |= BIT(5); /* DUPLICATE MODE */ + dispc_vp_write(dispc, hw_videoport, DISPC_VP_DSS_OLDI_CFG, oldi_cfg); + dispc_vp_write(dispc, hw_videoport + 1, DISPC_VP_DSS_OLDI_CFG, oldi_cfg); + break; + + case OLDI_DUAL_LINK: + oldi_cfg |= BIT(11); /* DUALMODESYNC */ + dispc_vp_write(dispc, hw_videoport, DISPC_VP_DSS_OLDI_CFG, oldi_cfg); + dispc_vp_write(dispc, hw_videoport + 1, DISPC_VP_DSS_OLDI_CFG, oldi_cfg); + break; + + default: + dev_warn(dispc->dev, "%s: Incorrect oldi mode. Returning.\n", +__func__); + return; + } while (!(oldi_reset_bit & dispc_read(dispc, DSS_SYSSTATUS)) && count < 1) This feels a bit hacky: - The function is dispc_enable_oldi, but the above code also disables oldi. We have code in dispc_vp_unprepare() which disables OLDI at the moment. - The function takes hw_videoport as a parameter, and is designed to work on that videoport. The above operates on two videoports. Isn't the function also called for hw_videoport +1, which would result in reg writes to hw_videoport + 2? - No matching code in dispc_vp_unprepare Obviously the duplicate mode (I presume that's "cloning") and the dual link complicate things here, and I have to say I haven't worked with such setups. But I think somehow this should be restructured so that common configuration (common to the OLDIs) is done somewhere else. I would guess that there are other drivers that support cloning and dual mode. Did you have a look how they handle things? Tomi
Re: [Intel-gfx] [PATCH v2 06/21] drm/i915/gt: Batch TLB invalidations
On 27/07/2022 12:48, Mauro Carvalho Chehab wrote: On Wed, 20 Jul 2022 11:49:59 +0100 Tvrtko Ursulin wrote: On 20/07/2022 08:13, Mauro Carvalho Chehab wrote: On Mon, 18 Jul 2022 14:52:05 +0100 Tvrtko Ursulin wrote: On 14/07/2022 13:06, Mauro Carvalho Chehab wrote: From: Chris Wilson Invalidate TLB in patch, in order to reduce performance regressions. "in batches"? Yeah. Will fix it. +void vma_invalidate_tlb(struct i915_address_space *vm, u32 tlb) +{ + /* +* Before we release the pages that were bound by this vma, we +* must invalidate all the TLBs that may still have a reference +* back to our physical address. It only needs to be done once, +* so after updating the PTE to point away from the pages, record +* the most recent TLB invalidation seqno, and if we have not yet +* flushed the TLBs upon release, perform a full invalidation. +*/ + WRITE_ONCE(tlb, intel_gt_next_invalidate_tlb_full(vm->gt)); Shouldn't tlb be a pointer for this to make sense? Oh, my mistake! Will fix at the next version. diff --git a/drivers/gpu/drm/i915/gt/intel_ppgtt.c b/drivers/gpu/drm/i915/gt/intel_ppgtt.c index d8b94d638559..2da6c82a8bd2 100644 --- a/drivers/gpu/drm/i915/gt/intel_ppgtt.c +++ b/drivers/gpu/drm/i915/gt/intel_ppgtt.c @@ -206,8 +206,12 @@ void ppgtt_bind_vma(struct i915_address_space *vm, void ppgtt_unbind_vma(struct i915_address_space *vm, struct i915_vma_resource *vma_res) { - if (vma_res->allocated) - vm->clear_range(vm, vma_res->start, vma_res->vma_size); + if (!vma_res->allocated) + return; + + vm->clear_range(vm, vma_res->start, vma_res->vma_size); + if (vma_res->tlb) + vma_invalidate_tlb(vm, *vma_res->tlb); The patch is about more than batching? If there is a security hole in this area (unbind) with the current code? No, I don't think there's a security hole. The rationale for this is not due to it. In this case obvious question is why are these changes in the patch which declares itself to be about batching invalidations? Because... Because vma_invalidate_tlb() basically stores a TLB seqno, but the actual invalidation is deferred to when the pages are unset, at __i915_gem_object_unset_pages(). So, what happens is: - on VMA sync mode, the need to invalidate TLB is marked at __vma_put_pages(), before VMA unbind; - on async, this is deferred to happen at ppgtt_unbind_vma(), where it marks the need to invalidate TLBs. On both cases, __i915_gem_object_unset_pages() is called later, when the driver is ready to unmap the page. Sorry still not clear to me why is the patch moving marking of the need to invalidate (regardless if it a bit like today, or a seqno like in this patch) from bind to unbind? What if the seqno was stored in i915_vma_bind, where the bit is set today, and all the hunks which touch the unbind and evict would disappear from the patch. What wouldn't work in that case, if anything? Regards, Tvrtko I am explaining why it looks to me that the patch is doing two things. Implementing batching _and_ adding invalidation points at VMA unbind sites, while so far we had it at backing store release only. Maybe I am wrong and perhaps I am too slow to pick up on the explanation here. So if the patch is doing two things please split it up. I am further confused by the invalidation call site in evict and in unbind - why there can't be one logical site since the logical sequence is evict -> unbind. The invalidation happens only on one place: __i915_gem_object_unset_pages(). Despite its name, vma_invalidate_tlb() just marks the need of doing TLB invalidation. Regards, Mauro
[PATCH v3 0/6] drm/i915: reduce TLB performance regressions
Doing TLB invalidation cause performance regressions, like: [424.370996] i915 :00:02.0: [drm] *ERROR* rcs0 TLB invalidation did not complete in 4ms! As reported at: https://gitlab.freedesktop.org/drm/intel/-/issues/6424 as this is an expensive operation. So, reduce the need of it by: - checking if the engine is awake; - checking if the engine is not wedged; - batching operations. Additionally, add a workaround for a known hardware issue on some GPUs. In order to double-check that this series won't be introducing any regressions, I used this new IGT test: https://patchwork.freedesktop.org/patch/495684/?series=106757=1 Checking the results for 3 different patchsets, on Broadwell: 1) On the top of drm-tip (2022y-07m-14d-08h-35m-36) - e. g. with TLB invalidation and serialization patches: $ sudo build/tests/gem_exec_tlb|grep Subtest Subtest close-clear: SUCCESS (10.490s) Subtest madv-clear: SUCCESS (10.484s) Subtest u-unmap-clear: SUCCESS (10.527s) Subtest u-shrink-clear: SUCCESS (10.506s) Subtest close-dumb: SUCCESS (10.165s) Subtest madv-dumb: SUCCESS (10.177s) Subtest u-unmap-dumb: SUCCESS (10.172s) Subtest u-shrink-dumb: SUCCESS (10.172s) 2) With the new version of the batch TLB invalidation patches from this series: $ sudo build/tests/gem_exec_tlb|grep Subtest Subtest close-clear: SUCCESS (10.483s) Subtest madv-clear: SUCCESS (10.495s) Subtest u-unmap-clear: SUCCESS (10.545s) Subtest u-shrink-clear: SUCCESS (10.508s) Subtest close-dumb: SUCCESS (10.172s) Subtest madv-dumb: SUCCESS (10.169s) Subtest u-unmap-dumb: SUCCESS (10.174s) Subtest u-shrink-dumb: SUCCESS (10.176s) 3) Changing the TLB invalidation routine to do nothing[1]: $ sudo ~/freedesktop-igt/build/tests/gem_exec_tlb|grep Subtest (gem_exec_tlb:1958) CRITICAL: Test assertion failure function check_bo, file ../tests/i915/gem_exec_tlb.c:384: (gem_exec_tlb:1958) CRITICAL: Failed assertion: !sq (gem_exec_tlb:1958) CRITICAL: Found deadbeef in a new (clear) buffer after 3 tries! (gem_exec_tlb:1956) CRITICAL: Test assertion failure function check_bo, file ../tests/i915/gem_exec_tlb.c:384: (gem_exec_tlb:1956) CRITICAL: Failed assertion: !sq (gem_exec_tlb:1956) CRITICAL: Found deadbeef in a new (clear) buffer after 89 tries! (gem_exec_tlb:1957) CRITICAL: Test assertion failure function check_bo, file ../tests/i915/gem_exec_tlb.c:384: (gem_exec_tlb:1957) CRITICAL: Failed assertion: !sq (gem_exec_tlb:1957) CRITICAL: Found deadbeef in a new (clear) buffer after 256 tries! (gem_exec_tlb:1960) CRITICAL: Test assertion failure function check_bo, file ../tests/i915/gem_exec_tlb.c:384: (gem_exec_tlb:1960) CRITICAL: Failed assertion: !sq (gem_exec_tlb:1960) CRITICAL: Found deadbeef in a new (clear) buffer after 845 tries! (gem_exec_tlb:1961) CRITICAL: Test assertion failure function check_bo, file ../tests/i915/gem_exec_tlb.c:384: (gem_exec_tlb:1961) CRITICAL: Failed assertion: !sq (gem_exec_tlb:1961) CRITICAL: Found deadbeef in a new (clear) buffer after 1138 tries! (gem_exec_tlb:1954) CRITICAL: Test assertion failure function check_bo, file ../tests/i915/gem_exec_tlb.c:384: (gem_exec_tlb:1954) CRITICAL: Failed assertion: !sq (gem_exec_tlb:1954) CRITICAL: Found deadbeef in a new (clear) buffer after 1359 tries! (gem_exec_tlb:1955) CRITICAL: Test assertion failure function check_bo, file ../tests/i915/gem_exec_tlb.c:384: (gem_exec_tlb:1955) CRITICAL: Failed assertion: !sq (gem_exec_tlb:1955) CRITICAL: Found deadbeef in a new (clear) buffer after 1794 tries! (gem_exec_tlb:1959) CRITICAL: Test assertion failure function check_bo, file ../tests/i915/gem_exec_tlb.c:384: (gem_exec_tlb:1959) CRITICAL: Failed assertion: !sq (gem_exec_tlb:1959) CRITICAL: Found deadbeef in a new (clear) buffer after 2139 tries! Dynamic subtest smem0 failed. DEBUG (gem_exec_tlb:1944) DEBUG: 2M hole:20 contains poison:6b6b6b6b (gem_exec_tlb:1944) DEBUG: Running writer for 20 at 30 on bcs0 (gem_exec_tlb:1944) DEBUG: Closing hole:20 on rcs0, sample:deadbeef (gem_exec_tlb:1944) DEBUG: Rechecking hole:20, sample:6b6b6b6b END Subtest close-clear: FAIL (10.434s) Subtest madv-clear: SUCCESS (10.479s) Subtest u-unmap-clear: SUCCESS (10.512s) In summary, the test does properly detect fail when TLB cache invalidation doesn't happen, as shown at result (3). It also shows that both current drm-tip and drm-tip with this series applied don't have TLB invalidation cache issues. [1] I applied this patch on the top of drm-tip: diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c
[PATCH v3 6/6] drm/i915/gt: describe the new tlb parameter at i915_vma_resource
TLB cache invalidation can happen on two different situations: 1. synchronously, at __vma_put_pages(); 2. asynchronously. On the first case, TLB cache invalidation happens inside __vma_put_pages(). So, no need to do it later on. However, on the second case, the pages will keep in memory until __i915_vma_evict() is called. So, we need to store the TLB data at struct i915_vma_resource, in order to do a TLB cache invalidation before allowing userspace to re-use the same memory. So, i915_vma_resource_unbind() has gained a new parameter in order to store the TLB data at the second case. Document it. Signed-off-by: Mauro Carvalho Chehab --- To avoid mailbombing on a large number of people, only mailing lists were C/C on the cover. See [PATCH v3 0/6] at: https://lore.kernel.org/all/cover.1658924372.git.mche...@kernel.org/ drivers/gpu/drm/i915/i915_vma_resource.c | 4 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_vma_resource.c b/drivers/gpu/drm/i915/i915_vma_resource.c index 5a67995ea5fe..4fe09ea0a825 100644 --- a/drivers/gpu/drm/i915/i915_vma_resource.c +++ b/drivers/gpu/drm/i915/i915_vma_resource.c @@ -216,6 +216,10 @@ i915_vma_resource_fence_notify(struct i915_sw_fence *fence, /** * i915_vma_resource_unbind - Unbind a vma resource * @vma_res: The vma resource to unbind. + * @tlb: pointer to vma->obj->mm.tlb associated with the resource + * to be stored at vma_res->tlb. When not-NULL, it will be used + * to do TLB cache invalidation before freeing a VMA resource. + * used only for async unbind. * * At this point this function does little more than publish a fence that * signals immediately unless signaling is held back. -- 2.36.1
[PATCH v3 5/6] drm/i915/gt: Batch TLB invalidations
From: Chris Wilson Invalidate TLB in batches, in order to reduce performance regressions. Currently, every caller performs a full barrier around a TLB invalidation, ignoring all other invalidations that may have already removed their PTEs from the cache. As this is a synchronous operation and can be quite slow, we cause multiple threads to contend on the TLB invalidate mutex blocking userspace. We only need to invalidate the TLB once after replacing our PTE to ensure that there is no possible continued access to the physical address before releasing our pages. By tracking a seqno for each full TLB invalidate we can quickly determine if one has been performed since rewriting the PTE, and only if necessary trigger one for ourselves. That helps to reduce the performance regression introduced by TLB invalidate logic. [mchehab: rebased to not require moving the code to a separate file] Cc: sta...@vger.kernel.org Fixes: 7938d61591d3 ("drm/i915: Flush TLBs before releasing backing store") Suggested-by: Tvrtko Ursulin Signed-off-by: Chris Wilson Cc: Fei Yang Signed-off-by: Mauro Carvalho Chehab --- To avoid mailbombing on a large number of people, only mailing lists were C/C on the cover. See [PATCH v3 0/6] at: https://lore.kernel.org/all/cover.1658924372.git.mche...@kernel.org/ .../gpu/drm/i915/gem/i915_gem_object_types.h | 3 +- drivers/gpu/drm/i915/gem/i915_gem_pages.c | 21 +--- drivers/gpu/drm/i915/gt/intel_gt.c| 53 ++- drivers/gpu/drm/i915/gt/intel_gt.h| 12 - drivers/gpu/drm/i915/gt/intel_gt_types.h | 18 ++- drivers/gpu/drm/i915/gt/intel_ppgtt.c | 8 ++- drivers/gpu/drm/i915/i915_vma.c | 33 +--- drivers/gpu/drm/i915/i915_vma.h | 1 + drivers/gpu/drm/i915/i915_vma_resource.c | 5 +- drivers/gpu/drm/i915/i915_vma_resource.h | 6 ++- 10 files changed, 125 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h index 5cf36a130061..9f6b14ec189a 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h @@ -335,7 +335,6 @@ struct drm_i915_gem_object { #define I915_BO_READONLY BIT(7) #define I915_TILING_QUIRK_BIT 8 /* unknown swizzling; do not release! */ #define I915_BO_PROTECTED BIT(9) -#define I915_BO_WAS_BOUND_BIT 10 /** * @mem_flags - Mutable placement-related flags * @@ -616,6 +615,8 @@ struct drm_i915_gem_object { * pages were last acquired. */ bool dirty:1; + + u32 tlb; } mm; struct { diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pages.c b/drivers/gpu/drm/i915/gem/i915_gem_pages.c index 6835279943df..8357dbdcab5c 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_pages.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_pages.c @@ -191,6 +191,18 @@ static void unmap_object(struct drm_i915_gem_object *obj, void *ptr) vunmap(ptr); } +static void flush_tlb_invalidate(struct drm_i915_gem_object *obj) +{ + struct drm_i915_private *i915 = to_i915(obj->base.dev); + struct intel_gt *gt = to_gt(i915); + + if (!obj->mm.tlb) + return; + + intel_gt_invalidate_tlb(gt, obj->mm.tlb); + obj->mm.tlb = 0; +} + struct sg_table * __i915_gem_object_unset_pages(struct drm_i915_gem_object *obj) { @@ -216,14 +228,7 @@ __i915_gem_object_unset_pages(struct drm_i915_gem_object *obj) __i915_gem_object_reset_page_iter(obj); obj->mm.page_sizes.phys = obj->mm.page_sizes.sg = 0; - if (test_and_clear_bit(I915_BO_WAS_BOUND_BIT, >flags)) { - struct drm_i915_private *i915 = to_i915(obj->base.dev); - struct intel_gt *gt = to_gt(i915); - intel_wakeref_t wakeref; - - with_intel_gt_pm_if_awake(gt, wakeref) - intel_gt_invalidate_tlbs(gt); - } + flush_tlb_invalidate(obj); return pages; } diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c index 5c55a90672f4..f435e06125aa 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.c +++ b/drivers/gpu/drm/i915/gt/intel_gt.c @@ -38,8 +38,6 @@ static void __intel_gt_init_early(struct intel_gt *gt) { spin_lock_init(>irq_lock); - mutex_init(>tlb_invalidate_lock); - INIT_LIST_HEAD(>closed_vma); spin_lock_init(>closed_lock); @@ -50,6 +48,8 @@ static void __intel_gt_init_early(struct intel_gt *gt) intel_gt_init_reset(gt); intel_gt_init_requests(gt); intel_gt_init_timelines(gt); + mutex_init(>tlb.invalidate_lock); + seqcount_mutex_init(>tlb.seqno, >tlb.invalidate_lock); intel_gt_pm_init_early(gt); intel_uc_init_early(>uc); @@ -770,6 +770,7 @@ void intel_gt_driver_late_release_all(struct drm_i915_private
[PATCH v3 3/6] drm/i915/gt: Invalidate TLB of the OA unit at TLB invalidations
From: Chris Wilson Ensure that the TLB of the OA unit is also invalidated on gen12 HW, as just invalidating the TLB of an engine is not enough. Cc: sta...@vger.kernel.org Fixes: 7938d61591d3 ("drm/i915: Flush TLBs before releasing backing store") Signed-off-by: Chris Wilson Cc: Fei Yang Reviewed-by: Andi Shyti Acked-by: Tvrtko Ursulin Acked-by: Thomas Hellström Signed-off-by: Mauro Carvalho Chehab --- To avoid mailbombing on a large number of people, only mailing lists were C/C on the cover. See [PATCH v3 0/6] at: https://lore.kernel.org/all/cover.1658924372.git.mche...@kernel.org/ drivers/gpu/drm/i915/gt/intel_gt.c | 10 ++ 1 file changed, 10 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c index c4d43da84d8e..1d84418e8676 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.c +++ b/drivers/gpu/drm/i915/gt/intel_gt.c @@ -11,6 +11,7 @@ #include "pxp/intel_pxp.h" #include "i915_drv.h" +#include "i915_perf_oa_regs.h" #include "intel_context.h" #include "intel_engine_pm.h" #include "intel_engine_regs.h" @@ -969,6 +970,15 @@ void intel_gt_invalidate_tlbs(struct intel_gt *gt) awake |= engine->mask; } + /* Wa_2207587034:tgl,dg1,rkl,adl-s,adl-p */ + if (awake && + (IS_TIGERLAKE(i915) || +IS_DG1(i915) || +IS_ROCKETLAKE(i915) || +IS_ALDERLAKE_S(i915) || +IS_ALDERLAKE_P(i915))) + intel_uncore_write_fw(uncore, GEN12_OA_TLB_INV_CR, 1); + spin_unlock_irq(>lock); for_each_engine_masked(engine, gt, awake, tmp) { -- 2.36.1
[PATCH v3 2/6] drm/i915/gt: document with_intel_gt_pm_if_awake()
Add a kernel-doc markup to document this new macro. Reviewed-by: Tvrtko Ursulin Signed-off-by: Mauro Carvalho Chehab --- To avoid mailbombing on a large number of people, only mailing lists were C/C on the cover. See [PATCH v3 0/6] at: https://lore.kernel.org/all/cover.1658924372.git.mche...@kernel.org/ drivers/gpu/drm/i915/gt/intel_gt_pm.h | 8 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.h b/drivers/gpu/drm/i915/gt/intel_gt_pm.h index a334787a4939..6c9a46452364 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm.h +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.h @@ -55,6 +55,14 @@ static inline void intel_gt_pm_might_put(struct intel_gt *gt) for (tmp = 1, intel_gt_pm_get(gt); tmp; \ intel_gt_pm_put(gt), tmp = 0) +/** + * with_intel_gt_pm_if_awake - if GT is PM awake, get a reference to prevent + * it to sleep, run some code and then asynchrously put the reference + * away. + * + * @gt: pointer to the gt + * @wf: pointer to a temporary wakeref. + */ #define with_intel_gt_pm_if_awake(gt, wf) \ for (wf = intel_gt_pm_get_if_awake(gt); wf; intel_gt_pm_put_async(gt), wf = 0) -- 2.36.1
[PATCH v3 1/6] drm/i915/gt: Ignore TLB invalidations on idle engines
From: Chris Wilson Check if the device is powered down prior to any engine activity, as, on such cases, all the TLBs were already invalidated, so an explicit TLB invalidation is not needed, thus reducing the performance regression impact due to it. This becomes more significant with GuC, as it can only do so when the connection to the GuC is awake. Cc: sta...@vger.kernel.org Fixes: 7938d61591d3 ("drm/i915: Flush TLBs before releasing backing store") Signed-off-by: Chris Wilson Cc: Fei Yang Reviewed-by: Andi Shyti Acked-by: Thomas Hellström Acked-by: Tvrtko Ursulin Signed-off-by: Mauro Carvalho Chehab --- To avoid mailbombing on a large number of people, only mailing lists were C/C on the cover. See [PATCH v3 0/6] at: https://lore.kernel.org/all/cover.1658924372.git.mche...@kernel.org/ drivers/gpu/drm/i915/gem/i915_gem_pages.c | 10 ++ drivers/gpu/drm/i915/gt/intel_gt.c| 17 ++--- drivers/gpu/drm/i915/gt/intel_gt_pm.h | 3 +++ 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pages.c b/drivers/gpu/drm/i915/gem/i915_gem_pages.c index 97c820eee115..6835279943df 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_pages.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_pages.c @@ -6,14 +6,15 @@ #include +#include "gt/intel_gt.h" +#include "gt/intel_gt_pm.h" + #include "i915_drv.h" #include "i915_gem_object.h" #include "i915_scatterlist.h" #include "i915_gem_lmem.h" #include "i915_gem_mman.h" -#include "gt/intel_gt.h" - void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj, struct sg_table *pages, unsigned int sg_page_sizes) @@ -217,10 +218,11 @@ __i915_gem_object_unset_pages(struct drm_i915_gem_object *obj) if (test_and_clear_bit(I915_BO_WAS_BOUND_BIT, >flags)) { struct drm_i915_private *i915 = to_i915(obj->base.dev); + struct intel_gt *gt = to_gt(i915); intel_wakeref_t wakeref; - with_intel_runtime_pm_if_active(>runtime_pm, wakeref) - intel_gt_invalidate_tlbs(to_gt(i915)); + with_intel_gt_pm_if_awake(gt, wakeref) + intel_gt_invalidate_tlbs(gt); } return pages; diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c index 68c2b0d8f187..c4d43da84d8e 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.c +++ b/drivers/gpu/drm/i915/gt/intel_gt.c @@ -12,6 +12,7 @@ #include "i915_drv.h" #include "intel_context.h" +#include "intel_engine_pm.h" #include "intel_engine_regs.h" #include "intel_ggtt_gmch.h" #include "intel_gt.h" @@ -924,6 +925,7 @@ void intel_gt_invalidate_tlbs(struct intel_gt *gt) struct drm_i915_private *i915 = gt->i915; struct intel_uncore *uncore = gt->uncore; struct intel_engine_cs *engine; + intel_engine_mask_t awake, tmp; enum intel_engine_id id; const i915_reg_t *regs; unsigned int num = 0; @@ -947,26 +949,31 @@ void intel_gt_invalidate_tlbs(struct intel_gt *gt) GEM_TRACE("\n"); - assert_rpm_wakelock_held(>runtime_pm); - mutex_lock(>tlb_invalidate_lock); intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL); spin_lock_irq(>lock); /* serialise invalidate with GT reset */ + awake = 0; for_each_engine(engine, gt, id) { struct reg_and_bit rb; + if (!intel_engine_pm_is_awake(engine)) + continue; + rb = get_reg_and_bit(engine, regs == gen8_regs, regs, num); if (!i915_mmio_reg_offset(rb.reg)) continue; intel_uncore_write_fw(uncore, rb.reg, rb.bit); + awake |= engine->mask; } spin_unlock_irq(>lock); - for_each_engine(engine, gt, id) { + for_each_engine_masked(engine, gt, awake, tmp) { + struct reg_and_bit rb; + /* * HW architecture suggest typical invalidation time at 40us, * with pessimistic cases up to 100us and a recommendation to @@ -974,12 +981,8 @@ void intel_gt_invalidate_tlbs(struct intel_gt *gt) */ const unsigned int timeout_us = 100; const unsigned int timeout_ms = 4; - struct reg_and_bit rb; rb = get_reg_and_bit(engine, regs == gen8_regs, regs, num); - if (!i915_mmio_reg_offset(rb.reg)) - continue; - if (__intel_wait_for_register_fw(uncore, rb.reg, rb.bit, 0, timeout_us, timeout_ms, diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.h b/drivers/gpu/drm/i915/gt/intel_gt_pm.h index bc898df7a48c..a334787a4939 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm.h +++
[PATCH v3 4/6] drm/i915/gt: Skip TLB invalidations once wedged
From: Chris Wilson Skip all further TLB invalidations once the device is wedged and had been reset, as, on such cases, it can no longer process instructions on the GPU and the user no longer has access to the TLB's in each engine. So, an attempt to do a TLB cache invalidation will produce a timeout. That helps to reduce the performance regression introduced by TLB invalidate logic. Cc: sta...@vger.kernel.org Fixes: 7938d61591d3 ("drm/i915: Flush TLBs before releasing backing store") Signed-off-by: Chris Wilson Cc: Fei Yang Cc: Tvrtko Ursulin Reviewed-by: Andi Shyti Acked-by: Thomas Hellström Signed-off-by: Mauro Carvalho Chehab --- To avoid mailbombing on a large number of people, only mailing lists were C/C on the cover. See [PATCH v3 0/6] at: https://lore.kernel.org/all/cover.1658924372.git.mche...@kernel.org/ drivers/gpu/drm/i915/gt/intel_gt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c index 1d84418e8676..5c55a90672f4 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.c +++ b/drivers/gpu/drm/i915/gt/intel_gt.c @@ -934,6 +934,9 @@ void intel_gt_invalidate_tlbs(struct intel_gt *gt) if (I915_SELFTEST_ONLY(gt->awake == -ENODEV)) return; + if (intel_gt_is_wedged(gt)) + return; + if (GRAPHICS_VER(i915) == 12) { regs = gen12_regs; num = ARRAY_SIZE(gen12_regs); -- 2.36.1
Re: [PATCH] drm/tests: Split up test cases in igt_check_drm_format_min_pitch
Hi all, Friendly ping: is someone available to take this, please? Best Regards, - Maíra Canal On 7/17/22 15:43, Maíra Canal wrote: > The igt_check_drm_format_min_pitch() function had a lot of > KUNIT_EXPECT_* calls, all of which ended up allocating and initializing > various test assertion structures on the stack. > > This behavior was producing -Wframe-larger-than warnings on PowerPC, i386, > and MIPS architectures, such as: > > drivers/gpu/drm/tests/drm_format_test.c: In function > 'igt_check_drm_format_min_pitch': > drivers/gpu/drm/tests/drm_format_test.c:271:1: error: the frame size of > 3712 bytes is larger than 2048 bytes > > So, the igt_check_drm_format_min_pitch() test case was split into three > smaller functions: one testing single plane formats, one testing multiple > planes formats, and the other testing tiled formats. > > Reported-by: kernel test robot > Reported-by: Guenter Roeck > Signed-off-by: Maíra Canal > --- > drivers/gpu/drm/tests/drm_format_test.c | 16 ++-- > 1 file changed, 14 insertions(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/tests/drm_format_test.c > b/drivers/gpu/drm/tests/drm_format_test.c > index 056cb8599d6d..28f2b8f88818 100644 > --- a/drivers/gpu/drm/tests/drm_format_test.c > +++ b/drivers/gpu/drm/tests/drm_format_test.c > @@ -91,7 +91,7 @@ static void igt_check_drm_format_block_height(struct kunit > *test) > KUNIT_EXPECT_FALSE(test, drm_format_info_block_height(info, -1)); > } > > -static void igt_check_drm_format_min_pitch(struct kunit *test) > +static void igt_check_drm_format_min_pitch_for_single_plane(struct kunit > *test) > { > const struct drm_format_info *info = NULL; > > @@ -175,6 +175,11 @@ static void igt_check_drm_format_min_pitch(struct kunit > *test) > (uint64_t)UINT_MAX * 4); > KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, (UINT_MAX - > 1)), > (uint64_t)(UINT_MAX - 1) * 4); > +} > + > +static void igt_check_drm_format_min_pitch_for_multiple_planes(struct kunit > *test) > +{ > + const struct drm_format_info *info = NULL; > > /* Test 2 planes format */ > info = drm_format_info(DRM_FORMAT_NV12); > @@ -249,6 +254,11 @@ static void igt_check_drm_format_min_pitch(struct kunit > *test) > (uint64_t)(UINT_MAX - 1) / 2); > KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 2, (UINT_MAX - 1) > / 2), > (uint64_t)(UINT_MAX - 1) / 2); > +} > + > +static void igt_check_drm_format_min_pitch_for_tiled_format(struct kunit > *test) > +{ > + const struct drm_format_info *info = NULL; > > /* Test tiled format */ > info = drm_format_info(DRM_FORMAT_X0L2); > @@ -273,7 +283,9 @@ static void igt_check_drm_format_min_pitch(struct kunit > *test) > static struct kunit_case drm_format_tests[] = { > KUNIT_CASE(igt_check_drm_format_block_width), > KUNIT_CASE(igt_check_drm_format_block_height), > - KUNIT_CASE(igt_check_drm_format_min_pitch), > + KUNIT_CASE(igt_check_drm_format_min_pitch_for_single_plane), > + KUNIT_CASE(igt_check_drm_format_min_pitch_for_multiple_planes), > + KUNIT_CASE(igt_check_drm_format_min_pitch_for_tiled_format), > { } > }; >
Re: [Intel-gfx] [PATCH v2 06/21] drm/i915/gt: Batch TLB invalidations
On Wed, 20 Jul 2022 11:49:59 +0100 Tvrtko Ursulin wrote: > On 20/07/2022 08:13, Mauro Carvalho Chehab wrote: > > On Mon, 18 Jul 2022 14:52:05 +0100 > > Tvrtko Ursulin wrote: > > > >> > >> On 14/07/2022 13:06, Mauro Carvalho Chehab wrote: > >>> From: Chris Wilson > >>> > >>> Invalidate TLB in patch, in order to reduce performance regressions. > >> > >> "in batches"? > > > > Yeah. Will fix it. > > +void vma_invalidate_tlb(struct i915_address_space *vm, u32 tlb) > > +{ > > + /* > > +* Before we release the pages that were bound by this vma, we > > +* must invalidate all the TLBs that may still have a reference > > +* back to our physical address. It only needs to be done once, > > +* so after updating the PTE to point away from the pages, record > > +* the most recent TLB invalidation seqno, and if we have not yet > > +* flushed the TLBs upon release, perform a full invalidation. > > +*/ > > + WRITE_ONCE(tlb, intel_gt_next_invalidate_tlb_full(vm->gt)); > > Shouldn't tlb be a pointer for this to make sense? Oh, my mistake! Will fix at the next version. > > > >>> diff --git a/drivers/gpu/drm/i915/gt/intel_ppgtt.c > >>> b/drivers/gpu/drm/i915/gt/intel_ppgtt.c > >>> index d8b94d638559..2da6c82a8bd2 100644 > >>> --- a/drivers/gpu/drm/i915/gt/intel_ppgtt.c > >>> +++ b/drivers/gpu/drm/i915/gt/intel_ppgtt.c > >>> @@ -206,8 +206,12 @@ void ppgtt_bind_vma(struct i915_address_space *vm, > >>>void ppgtt_unbind_vma(struct i915_address_space *vm, > >>> struct i915_vma_resource *vma_res) > >>>{ > >>> - if (vma_res->allocated) > >>> - vm->clear_range(vm, vma_res->start, vma_res->vma_size); > >>> + if (!vma_res->allocated) > >>> + return; > >>> + > >>> + vm->clear_range(vm, vma_res->start, vma_res->vma_size); > >>> + if (vma_res->tlb) > >>> + vma_invalidate_tlb(vm, *vma_res->tlb); > >> > >> The patch is about more than batching? If there is a security hole in > >> this area (unbind) with the current code? > > > > No, I don't think there's a security hole. The rationale for this is > > not due to it. > > In this case obvious question is why are these changes in the patch > which declares itself to be about batching invalidations? Because... Because vma_invalidate_tlb() basically stores a TLB seqno, but the actual invalidation is deferred to when the pages are unset, at __i915_gem_object_unset_pages(). So, what happens is: - on VMA sync mode, the need to invalidate TLB is marked at __vma_put_pages(), before VMA unbind; - on async, this is deferred to happen at ppgtt_unbind_vma(), where it marks the need to invalidate TLBs. On both cases, __i915_gem_object_unset_pages() is called later, when the driver is ready to unmap the page. > I am explaining why it looks to me that the patch is doing two things. > Implementing batching _and_ adding invalidation points at VMA unbind > sites, while so far we had it at backing store release only. Maybe I am > wrong and perhaps I am too slow to pick up on the explanation here. > > So if the patch is doing two things please split it up. > > I am further confused by the invalidation call site in evict and in > unbind - why there can't be one logical site since the logical sequence > is evict -> unbind. The invalidation happens only on one place: __i915_gem_object_unset_pages(). Despite its name, vma_invalidate_tlb() just marks the need of doing TLB invalidation. Regards, Mauro
[PATCH 09/12] drm/format-helper: Rework XRGB8888-to-XRGB2101010 conversion
Update XRGB-to-XRGB2101010 conversion to support struct iosys_map and convert all users. Although these are single-plane color formats, the new interface supports multi-plane formats for consistency with drm_fb_blit(). Signed-off-by: Thomas Zimmermann --- drivers/gpu/drm/drm_format_helper.c | 35 + include/drm/drm_format_helper.h | 6 ++--- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index 155827eebe99..209f63b66c5f 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -504,26 +504,34 @@ static void drm_fb_xrgb_to_xrgb2101010_line(void *dbuf, const void *sbuf, un } /** - * drm_fb_xrgb_to_xrgb2101010_toio - Convert XRGB to XRGB2101010 clip - * buffer - * @dst: XRGB2101010 destination buffer (iomem) - * @dst_pitch: Number of bytes between two consecutive scanlines within dst - * @vaddr: XRGB source buffer + * drm_fb_xrgb_to_xrgb2101010 - Convert XRGB to XRGB2101010 clip buffer + * @dst: Array of XRGB2101010 destination buffers + * @dst_pitch: Array of numbers of bytes between two consecutive scanlines within dst + * @vmap: Array of XRGB source buffers * @fb: DRM framebuffer * @clip: Clip rectangle area to copy * * Drivers can use this function for XRGB2101010 devices that don't natively * support XRGB. */ -void drm_fb_xrgb_to_xrgb2101010_toio(void __iomem *dst, -unsigned int dst_pitch, const void *vaddr, -const struct drm_framebuffer *fb, -const struct drm_rect *clip) +void drm_fb_xrgb_to_xrgb2101010(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct drm_rect *clip) { - drm_fb_xfrm_toio(dst, dst_pitch, 4, vaddr, fb, clip, false, -drm_fb_xrgb_to_xrgb2101010_line); + static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = { + 0, 0, 0, 0 + }; + + if (!dst_pitch) + dst_pitch = default_dst_pitch; + + if (dst[0].is_iomem) + drm_fb_xfrm_toio(dst[0].vaddr_iomem, dst_pitch[0], 4, vmap[0].vaddr, fb, +clip, false, drm_fb_xrgb_to_xrgb2101010_line); + else + drm_fb_xfrm(dst[0].vaddr, dst_pitch[0], 4, vmap[0].vaddr, fb, + clip, false, drm_fb_xrgb_to_xrgb2101010_line); } -EXPORT_SYMBOL(drm_fb_xrgb_to_xrgb2101010_toio); static void drm_fb_xrgb_to_gray8_line(void *dbuf, const void *sbuf, unsigned int pixels) { @@ -628,8 +636,7 @@ int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t d } } else if (dst_format == DRM_FORMAT_XRGB2101010) { if (fb_format == DRM_FORMAT_XRGB) { - drm_fb_xrgb_to_xrgb2101010_toio(dst[0].vaddr_iomem, dst_pitch[0], - vmap[0].vaddr, fb, clip); + drm_fb_xrgb_to_xrgb2101010(dst, dst_pitch, vmap, fb, clip); return 0; } } diff --git a/include/drm/drm_format_helper.h b/include/drm/drm_format_helper.h index 8c633dbab5d6..6807440ce29c 100644 --- a/include/drm/drm_format_helper.h +++ b/include/drm/drm_format_helper.h @@ -29,9 +29,9 @@ void drm_fb_xrgb_to_rgb565(struct iosys_map *dst, const unsigned int *dst_pi void drm_fb_xrgb_to_rgb888(struct iosys_map *dst, const unsigned int *dst_pitch, const struct iosys_map *vmap, const struct drm_framebuffer *fb, const struct drm_rect *clip); -void drm_fb_xrgb_to_xrgb2101010_toio(void __iomem *dst, unsigned int dst_pitch, -const void *vaddr, const struct drm_framebuffer *fb, -const struct drm_rect *clip); +void drm_fb_xrgb_to_xrgb2101010(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct drm_rect *clip); void drm_fb_xrgb_to_gray8(void *dst, unsigned int dst_pitch, const void *vaddr, const struct drm_framebuffer *fb, const struct drm_rect *clip); -- 2.37.1
[PATCH 10/12] drm/format-helper: Rework XRGB8888-to-GRAY8 conversion
Update XRGB-to-GRAY8 conversion to support struct iosys_map and convert all users. Although these are single-plane color formats, the new interface supports multi-plane formats for consistency with drm_fb_blit(). Signed-off-by: Thomas Zimmermann --- drivers/gpu/drm/drm_format_helper.c | 25 +++-- drivers/gpu/drm/gud/gud_pipe.c | 7 +-- drivers/gpu/drm/tiny/st7586.c | 5 - include/drm/drm_format_helper.h | 5 +++-- 4 files changed, 31 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index 209f63b66c5f..521932fac491 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -552,9 +552,9 @@ static void drm_fb_xrgb_to_gray8_line(void *dbuf, const void *sbuf, unsigned /** * drm_fb_xrgb_to_gray8 - Convert XRGB to grayscale - * @dst: 8-bit grayscale destination buffer - * @dst_pitch: Number of bytes between two consecutive scanlines within dst - * @vaddr: XRGB source buffer + * @dst: Array of 8-bit grayscale destination buffers + * @dst_pitch: Array of number of bytes between two consecutive scanlines within dst + * @vmap: Array of XRGB source buffers * @fb: DRM framebuffer * @clip: Clip rectangle area to copy * @@ -567,10 +567,23 @@ static void drm_fb_xrgb_to_gray8_line(void *dbuf, const void *sbuf, unsigned * * ITU BT.601 is used for the RGB -> luma (brightness) conversion. */ -void drm_fb_xrgb_to_gray8(void *dst, unsigned int dst_pitch, const void *vaddr, - const struct drm_framebuffer *fb, const struct drm_rect *clip) +void drm_fb_xrgb_to_gray8(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct drm_rect *clip) { - drm_fb_xfrm(dst, dst_pitch, 1, vaddr, fb, clip, false, drm_fb_xrgb_to_gray8_line); + static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = { + 0, 0, 0, 0 + }; + + if (!dst_pitch) + dst_pitch = default_dst_pitch; + + if (dst[0].is_iomem) + drm_fb_xfrm_toio(dst[0].vaddr_iomem, dst_pitch[0], 1, vmap[0].vaddr, fb, +clip, false, drm_fb_xrgb_to_gray8_line); + else + drm_fb_xfrm(dst[0].vaddr, dst_pitch[0], 1, vmap[0].vaddr, fb, + clip, false, drm_fb_xrgb_to_gray8_line); } EXPORT_SYMBOL(drm_fb_xrgb_to_gray8); diff --git a/drivers/gpu/drm/gud/gud_pipe.c b/drivers/gpu/drm/gud/gud_pipe.c index 0caa228f736d..7c6dc2bcd14a 100644 --- a/drivers/gpu/drm/gud/gud_pipe.c +++ b/drivers/gpu/drm/gud/gud_pipe.c @@ -59,6 +59,7 @@ static size_t gud_xrgb_to_r124(u8 *dst, const struct drm_format_info *format unsigned int bits_per_pixel = 8 / block_width; unsigned int x, y, width, height; u8 pix, *pix8, *block = dst; /* Assign to silence compiler warning */ + struct iosys_map dst_map, vmap; size_t len; void *buf; @@ -74,7 +75,9 @@ static size_t gud_xrgb_to_r124(u8 *dst, const struct drm_format_info *format if (!buf) return 0; - drm_fb_xrgb_to_gray8(buf, 0, src, fb, rect); + iosys_map_set_vaddr(_map, buf); + iosys_map_set_vaddr(, src); + drm_fb_xrgb_to_gray8(_map, NULL, , fb, rect); pix8 = buf; for (y = 0; y < height; y++) { @@ -194,7 +197,7 @@ static int gud_prep_flush(struct gud_device *gdrm, struct drm_framebuffer *fb, goto end_cpu_access; } } else if (format->format == DRM_FORMAT_R8) { - drm_fb_xrgb_to_gray8(buf, 0, vaddr, fb, rect); + drm_fb_xrgb_to_gray8(, NULL, map_data, fb, rect); } else if (format->format == DRM_FORMAT_RGB332) { drm_fb_xrgb_to_rgb332(, NULL, map_data, fb, rect); } else if (format->format == DRM_FORMAT_RGB565) { diff --git a/drivers/gpu/drm/tiny/st7586.c b/drivers/gpu/drm/tiny/st7586.c index 8eddb020c43e..702350d0f8bc 100644 --- a/drivers/gpu/drm/tiny/st7586.c +++ b/drivers/gpu/drm/tiny/st7586.c @@ -69,12 +69,15 @@ static void st7586_xrgb_to_gray332(u8 *dst, void *vaddr, size_t len = (clip->x2 - clip->x1) * (clip->y2 - clip->y1); unsigned int x, y; u8 *src, *buf, val; + struct iosys_map dst_map, vmap; buf = kmalloc(len, GFP_KERNEL); if (!buf) return; - drm_fb_xrgb_to_gray8(buf, 0, vaddr, fb, clip); + iosys_map_set_vaddr(_map, buf); + iosys_map_set_vaddr(, vaddr); + drm_fb_xrgb_to_gray8(_map, NULL, , fb, clip); src = buf; for (y = clip->y1; y < clip->y2; y++) { diff --git a/include/drm/drm_format_helper.h
[PATCH 08/12] drm/format-helper: Rework RGB888-to-XRGB8888 conversion
Update RGB888-to-XRGB conversion to support struct iosys_map and convert all users. Although these are single-plane color formats, the new interface supports multi-plane formats for consistency with drm_fb_blit(). Signed-off-by: Thomas Zimmermann --- drivers/gpu/drm/drm_format_helper.c | 25 ++--- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index 5ef06f696657..155827eebe99 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -465,12 +465,24 @@ static void drm_fb_rgb888_to_xrgb_line(void *dbuf, const void *sbuf, unsigne } } -static void drm_fb_rgb888_to_xrgb_toio(void __iomem *dst, unsigned int dst_pitch, - const void *vaddr, const struct drm_framebuffer *fb, - const struct drm_rect *clip) +static void drm_fb_rgb888_to_xrgb(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *vmap, + const struct drm_framebuffer *fb, + const struct drm_rect *clip) { - drm_fb_xfrm_toio(dst, dst_pitch, 4, vaddr, fb, clip, false, -drm_fb_rgb888_to_xrgb_line); + static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = { + 0, 0, 0, 0 + }; + + if (!dst_pitch) + dst_pitch = default_dst_pitch; + + if (dst[0].is_iomem) + drm_fb_xfrm_toio(dst[0].vaddr_iomem, dst_pitch[0], 4, vmap[0].vaddr, fb, +clip, false, drm_fb_rgb888_to_xrgb_line); + else + drm_fb_xfrm(dst[0].vaddr, dst_pitch[0], 4, vmap[0].vaddr, fb, + clip, false, drm_fb_rgb888_to_xrgb_line); } static void drm_fb_xrgb_to_xrgb2101010_line(void *dbuf, const void *sbuf, unsigned int pixels) @@ -608,8 +620,7 @@ int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t d } } else if (dst_format == DRM_FORMAT_XRGB) { if (fb_format == DRM_FORMAT_RGB888) { - drm_fb_rgb888_to_xrgb_toio(dst[0].vaddr_iomem, dst_pitch[0], - vmap[0].vaddr, fb, clip); + drm_fb_rgb888_to_xrgb(dst, dst_pitch, vmap, fb, clip); return 0; } else if (fb_format == DRM_FORMAT_RGB565) { drm_fb_rgb565_to_xrgb(dst, dst_pitch, vmap, fb, clip); -- 2.37.1
[PATCH 12/12] drm/format-helper: Move destination-buffer handling into internal helper
The format-convertion helpers handle several cases for different values of destination buffer and pitch. Move that code into the internal helper drm_fb_xfrm() and avoid quite a bit of duplucation. Signed-off-by: Thomas Zimmermann --- drivers/gpu/drm/drm_format_helper.c | 169 +++- 1 file changed, 64 insertions(+), 105 deletions(-) diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index d296d181659d..35aebdb90165 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -41,11 +41,11 @@ unsigned int drm_fb_clip_offset(unsigned int pitch, const struct drm_format_info } EXPORT_SYMBOL(drm_fb_clip_offset); -/* TODO: Make this functon work with multi-plane formats. */ -static int drm_fb_xfrm(void *dst, unsigned long dst_pitch, unsigned long dst_pixsize, - const void *vaddr, const struct drm_framebuffer *fb, - const struct drm_rect *clip, bool vaddr_cached_hint, - void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels)) +/* TODO: Make this function work with multi-plane formats. */ +static int __drm_fb_xfrm(void *dst, unsigned long dst_pitch, unsigned long dst_pixsize, +const void *vaddr, const struct drm_framebuffer *fb, +const struct drm_rect *clip, bool vaddr_cached_hint, +void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels)) { unsigned long linepixels = drm_rect_width(clip); unsigned long lines = drm_rect_height(clip); @@ -84,11 +84,11 @@ static int drm_fb_xfrm(void *dst, unsigned long dst_pitch, unsigned long dst_pix return 0; } -/* TODO: Make this functon work with multi-plane formats. */ -static int drm_fb_xfrm_toio(void __iomem *dst, unsigned long dst_pitch, unsigned long dst_pixsize, - const void *vaddr, const struct drm_framebuffer *fb, - const struct drm_rect *clip, bool vaddr_cached_hint, - void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels)) +/* TODO: Make this function work with multi-plane formats. */ +static int __drm_fb_xfrm_toio(void __iomem *dst, unsigned long dst_pitch, unsigned long dst_pixsize, + const void *vaddr, const struct drm_framebuffer *fb, + const struct drm_rect *clip, bool vaddr_cached_hint, + void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels)) { unsigned long linepixels = drm_rect_width(clip); unsigned long lines = drm_rect_height(clip); @@ -129,6 +129,29 @@ static int drm_fb_xfrm_toio(void __iomem *dst, unsigned long dst_pitch, unsigned return 0; } +/* TODO: Make this function work with multi-plane formats. */ +static int drm_fb_xfrm(struct iosys_map *dst, + const unsigned int *dst_pitch, const u8 *dst_pixsize, + const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct drm_rect *clip, bool vaddr_cached_hint, + void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels)) +{ + static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = { + 0, 0, 0, 0 + }; + + if (!dst_pitch) + dst_pitch = default_dst_pitch; + + if (dst[0].is_iomem) + return __drm_fb_xfrm_toio(dst[0].vaddr_iomem, dst_pitch[0], dst_pixsize[0], + vmap[0].vaddr, fb, clip, false, xfrm_line); + else + return __drm_fb_xfrm(dst[0].vaddr, dst_pitch[0], dst_pixsize[0], +vmap[0].vaddr, fb, clip, false, xfrm_line); +} + + /** * drm_fb_memcpy - Copy clip buffer * @dst: Array of destination buffers @@ -213,14 +236,10 @@ void drm_fb_swab(struct iosys_map *dst, const unsigned int *dst_pitch, const struct iosys_map *vmap, const struct drm_framebuffer *fb, const struct drm_rect *clip, bool cached) { - static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = { - 0, 0, 0, 0 - }; const struct drm_format_info *format = fb->format; - u8 cpp = format->cpp[0]; void (*swab_line)(void *dbuf, const void *sbuf, unsigned int npixels); - switch (cpp) { + switch (format->cpp[0]) { case 4: swab_line = drm_fb_swab32_line; break; @@ -230,21 +249,10 @@ void drm_fb_swab(struct iosys_map *dst, const unsigned int *dst_pitch, default: drm_warn_once(fb->dev, "Format %p4cc has unsupported pixel size.\n", >format); - swab_line = NULL; - break; - } - if (!swab_line) return; +
[PATCH 11/12] drm/format-helper: Rework XRGB8888-to-MONO conversion
Update XRGB-to-MONO conversion to support struct iosys_map and convert all users. Although these are single-plane color formats, the new interface supports multi-plane formats for consistency with drm_fb_blit(). Signed-off-by: Thomas Zimmermann --- drivers/gpu/drm/drm_format_helper.c | 28 +++- drivers/gpu/drm/solomon/ssd130x.c | 7 --- drivers/gpu/drm/tiny/repaper.c | 6 +- include/drm/drm_format_helper.h | 5 +++-- 4 files changed, 31 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index 521932fac491..d296d181659d 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -680,9 +680,9 @@ static void drm_fb_gray8_to_mono_line(void *dbuf, const void *sbuf, unsigned int /** * drm_fb_xrgb_to_mono - Convert XRGB to monochrome - * @dst: monochrome destination buffer (0=black, 1=white) - * @dst_pitch: Number of bytes between two consecutive scanlines within dst - * @vaddr: XRGB source buffer + * @dst: Array of monochrome destination buffers (0=black, 1=white) + * @dst_pitch: Array of numbers of bytes between two consecutive scanlines within dst + * @vmap: Array of XRGB source buffers * @fb: DRM framebuffer * @clip: Clip rectangle area to copy * @@ -700,26 +700,36 @@ static void drm_fb_gray8_to_mono_line(void *dbuf, const void *sbuf, unsigned int * x-coordinate that is a multiple of 8, then the caller must take care itself * of supplying a suitable clip rectangle. */ -void drm_fb_xrgb_to_mono(void *dst, unsigned int dst_pitch, const void *vaddr, -const struct drm_framebuffer *fb, const struct drm_rect *clip) +void drm_fb_xrgb_to_mono(struct iosys_map *dst, const unsigned int *dst_pitch, +const struct iosys_map *vmap, const struct drm_framebuffer *fb, +const struct drm_rect *clip) { + static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = { + 0, 0, 0, 0 + }; unsigned int linepixels = drm_rect_width(clip); unsigned int lines = drm_rect_height(clip); unsigned int cpp = fb->format->cpp[0]; unsigned int len_src32 = linepixels * cpp; struct drm_device *dev = fb->dev; + void *vaddr = vmap[0].vaddr; + unsigned int dst_pitch_0; unsigned int y; - u8 *mono = dst, *gray8; + u8 *mono = dst[0].vaddr, *gray8; u32 *src32; if (drm_WARN_ON(dev, fb->format->format != DRM_FORMAT_XRGB)) return; + if (!dst_pitch) + dst_pitch = default_dst_pitch; + dst_pitch_0 = dst_pitch[0]; + /* * The mono destination buffer contains 1 bit per pixel */ - if (!dst_pitch) - dst_pitch = DIV_ROUND_UP(linepixels, 8); + if (!dst_pitch_0) + dst_pitch_0 = DIV_ROUND_UP(linepixels, 8); /* * The cma memory is write-combined so reads are uncached. @@ -744,7 +754,7 @@ void drm_fb_xrgb_to_mono(void *dst, unsigned int dst_pitch, const void *vadd drm_fb_xrgb_to_gray8_line(gray8, src32, linepixels); drm_fb_gray8_to_mono_line(mono, gray8, linepixels); vaddr += fb->pitches[0]; - mono += dst_pitch; + mono += dst_pitch_0; } kfree(src32); diff --git a/drivers/gpu/drm/solomon/ssd130x.c b/drivers/gpu/drm/solomon/ssd130x.c index 5a3e3b78cd9e..aa7329a65c98 100644 --- a/drivers/gpu/drm/solomon/ssd130x.c +++ b/drivers/gpu/drm/solomon/ssd130x.c @@ -537,11 +537,11 @@ static void ssd130x_clear_screen(struct ssd130x_device *ssd130x) kfree(buf); } -static int ssd130x_fb_blit_rect(struct drm_framebuffer *fb, const struct iosys_map *map, +static int ssd130x_fb_blit_rect(struct drm_framebuffer *fb, const struct iosys_map *vmap, struct drm_rect *rect) { struct ssd130x_device *ssd130x = drm_to_ssd130x(fb->dev); - void *vmap = map->vaddr; /* TODO: Use mapping abstraction properly */ + struct iosys_map dst; unsigned int dst_pitch; int ret = 0; u8 *buf = NULL; @@ -555,7 +555,8 @@ static int ssd130x_fb_blit_rect(struct drm_framebuffer *fb, const struct iosys_m if (!buf) return -ENOMEM; - drm_fb_xrgb_to_mono(buf, dst_pitch, vmap, fb, rect); + iosys_map_set_vaddr(, buf); + drm_fb_xrgb_to_mono(, _pitch, vmap, fb, rect); ssd130x_update_rect(ssd130x, buf, rect); diff --git a/drivers/gpu/drm/tiny/repaper.c b/drivers/gpu/drm/tiny/repaper.c index 013790c45d0a..0cdf6ab8fcc5 100644 --- a/drivers/gpu/drm/tiny/repaper.c +++ b/drivers/gpu/drm/tiny/repaper.c @@ -513,6 +513,8 @@ static int repaper_fb_dirty(struct drm_framebuffer *fb) { struct drm_gem_cma_object *cma_obj =
[PATCH 06/12] drm/format-helper: Rework XRGB8888-to-RGB888 conversion
Update XRGB-to-RGB888 conversion to support struct iosys_map and convert all users. Although these are single-plane color formats, the new interface supports multi-plane formats for consistency with drm_fb_blit(). Signed-off-by: Thomas Zimmermann --- drivers/gpu/drm/drm_format_helper.c | 48 - drivers/gpu/drm/gud/gud_pipe.c | 2 +- drivers/gpu/drm/tiny/cirrus.c | 3 +- include/drm/drm_format_helper.h | 8 ++--- 4 files changed, 25 insertions(+), 36 deletions(-) diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index 8bf5655f5ce0..4edab44336d8 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -383,41 +383,34 @@ static void drm_fb_xrgb_to_rgb888_line(void *dbuf, const void *sbuf, unsigne /** * drm_fb_xrgb_to_rgb888 - Convert XRGB to RGB888 clip buffer - * @dst: RGB888 destination buffer - * @dst_pitch: Number of bytes between two consecutive scanlines within dst - * @src: XRGB source buffer + * @dst: Array of RGB888 destination buffers + * @dst_pitch: Array of numbers of bytes between two consecutive scanlines within dst + * @vmap: Array of XRGB source buffers * @fb: DRM framebuffer * @clip: Clip rectangle area to copy * * Drivers can use this function for RGB888 devices that don't natively * support XRGB. */ -void drm_fb_xrgb_to_rgb888(void *dst, unsigned int dst_pitch, const void *src, - const struct drm_framebuffer *fb, const struct drm_rect *clip) +void drm_fb_xrgb_to_rgb888(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct drm_rect *clip) { - drm_fb_xfrm(dst, dst_pitch, 3, src, fb, clip, false, drm_fb_xrgb_to_rgb888_line); -} -EXPORT_SYMBOL(drm_fb_xrgb_to_rgb888); + static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = { + 0, 0, 0, 0 + }; -/** - * drm_fb_xrgb_to_rgb888_toio - Convert XRGB to RGB888 clip buffer - * @dst: RGB565 destination buffer (iomem) - * @dst_pitch: Number of bytes between two consecutive scanlines within dst - * @vaddr: XRGB source buffer - * @fb: DRM framebuffer - * @clip: Clip rectangle area to copy - * - * Drivers can use this function for RGB888 devices that don't natively - * support XRGB. - */ -void drm_fb_xrgb_to_rgb888_toio(void __iomem *dst, unsigned int dst_pitch, - const void *vaddr, const struct drm_framebuffer *fb, - const struct drm_rect *clip) -{ - drm_fb_xfrm_toio(dst, dst_pitch, 3, vaddr, fb, clip, false, -drm_fb_xrgb_to_rgb888_line); + if (!dst_pitch) + dst_pitch = default_dst_pitch; + + if (dst[0].is_iomem) + drm_fb_xfrm_toio(dst[0].vaddr_iomem, dst_pitch[0], 3, vmap[0].vaddr, fb, +clip, false, drm_fb_xrgb_to_rgb888_line); + else + drm_fb_xfrm(dst[0].vaddr, dst_pitch[0], 3, vmap[0].vaddr, fb, + clip, false, drm_fb_xrgb_to_rgb888_line); } -EXPORT_SYMBOL(drm_fb_xrgb_to_rgb888_toio); +EXPORT_SYMBOL(drm_fb_xrgb_to_rgb888); static void drm_fb_rgb565_to_xrgb_line(void *dbuf, const void *sbuf, unsigned int pixels) { @@ -598,8 +591,7 @@ int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t d } } else if (dst_format == DRM_FORMAT_RGB888) { if (fb_format == DRM_FORMAT_XRGB) { - drm_fb_xrgb_to_rgb888_toio(dst[0].vaddr_iomem, dst_pitch[0], - vmap[0].vaddr, fb, clip); + drm_fb_xrgb_to_rgb888(dst, dst_pitch, vmap, fb, clip); return 0; } } else if (dst_format == DRM_FORMAT_XRGB) { diff --git a/drivers/gpu/drm/gud/gud_pipe.c b/drivers/gpu/drm/gud/gud_pipe.c index a43eb6645352..0caa228f736d 100644 --- a/drivers/gpu/drm/gud/gud_pipe.c +++ b/drivers/gpu/drm/gud/gud_pipe.c @@ -201,7 +201,7 @@ static int gud_prep_flush(struct gud_device *gdrm, struct drm_framebuffer *fb, drm_fb_xrgb_to_rgb565(, NULL, map_data, fb, rect, gud_is_big_endian()); } else if (format->format == DRM_FORMAT_RGB888) { - drm_fb_xrgb_to_rgb888(buf, 0, vaddr, fb, rect); + drm_fb_xrgb_to_rgb888(, NULL, map_data, fb, rect); } else { len = gud_xrgb_to_color(buf, format, vaddr, fb, rect); } diff --git a/drivers/gpu/drm/tiny/cirrus.c b/drivers/gpu/drm/tiny/cirrus.c index 9cd398e4700b..354d5e854a6f 100644 ---
[PATCH 03/12] drm/format-helper: Convert drm_fb_swab() to struct iosys_map
Convert drm_fb_swab() to use struct iosys_map() and convert users. The new interface supports multi-plane color formats. Signed-off-by: Thomas Zimmermann --- drivers/gpu/drm/drm_format_helper.c | 38 + drivers/gpu/drm/drm_mipi_dbi.c | 2 +- drivers/gpu/drm/gud/gud_pipe.c | 2 +- include/drm/drm_format_helper.h | 6 ++--- 4 files changed, 33 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index 49589b442f18..fa22d3cb11e8 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -196,9 +196,9 @@ static void drm_fb_swab32_line(void *dbuf, const void *sbuf, unsigned int pixels /** * drm_fb_swab - Swap bytes into clip buffer - * @dst: Destination buffer - * @dst_pitch: Number of bytes between two consecutive scanlines within dst - * @src: Source buffer + * @dst: Array of destination buffers + * @dst_pitch: Array of numbers of bytes between two consecutive scanlines within dst + * @vmap: Array of source buffers * @fb: DRM framebuffer * @clip: Clip rectangle area to copy * @cached: Source buffer is mapped cached (eg. not write-combined) @@ -209,24 +209,42 @@ static void drm_fb_swab32_line(void *dbuf, const void *sbuf, unsigned int pixels * This function does not apply clipping on dst, i.e. the destination * is at the top-left corner. */ -void drm_fb_swab(void *dst, unsigned int dst_pitch, const void *src, -const struct drm_framebuffer *fb, const struct drm_rect *clip, -bool cached) +void drm_fb_swab(struct iosys_map *dst, const unsigned int *dst_pitch, +const struct iosys_map *vmap, const struct drm_framebuffer *fb, +const struct drm_rect *clip, bool cached) { - u8 cpp = fb->format->cpp[0]; + static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = { + 0, 0, 0, 0 + }; + const struct drm_format_info *format = fb->format; + u8 cpp = format->cpp[0]; + void (*swab_line)(void *dbuf, const void *sbuf, unsigned int npixels); switch (cpp) { case 4: - drm_fb_xfrm(dst, dst_pitch, cpp, src, fb, clip, cached, drm_fb_swab32_line); + swab_line = drm_fb_swab32_line; break; case 2: - drm_fb_xfrm(dst, dst_pitch, cpp, src, fb, clip, cached, drm_fb_swab16_line); + swab_line = drm_fb_swab16_line; break; default: drm_warn_once(fb->dev, "Format %p4cc has unsupported pixel size.\n", - >format->format); + >format); + swab_line = NULL; break; } + if (!swab_line) + return; + + if (!dst_pitch) + dst_pitch = default_dst_pitch; + + if (dst->is_iomem) + drm_fb_xfrm_toio(dst[0].vaddr_iomem, dst_pitch[0], cpp, +vmap[0].vaddr, fb, clip, cached, swab_line); + else + drm_fb_xfrm(dst[0].vaddr, dst_pitch[0], cpp, vmap[0].vaddr, fb, + clip, cached, swab_line); } EXPORT_SYMBOL(drm_fb_swab); diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c index 22451806fb5c..973a75585cad 100644 --- a/drivers/gpu/drm/drm_mipi_dbi.c +++ b/drivers/gpu/drm/drm_mipi_dbi.c @@ -221,7 +221,7 @@ int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb, switch (fb->format->format) { case DRM_FORMAT_RGB565: if (swap) - drm_fb_swab(dst, 0, src, fb, clip, !gem->import_attach); + drm_fb_swab(_map, NULL, data, fb, clip, !gem->import_attach); else drm_fb_memcpy(_map, NULL, data, fb, clip); break; diff --git a/drivers/gpu/drm/gud/gud_pipe.c b/drivers/gpu/drm/gud/gud_pipe.c index 449c95a4aee0..a15cda9ba058 100644 --- a/drivers/gpu/drm/gud/gud_pipe.c +++ b/drivers/gpu/drm/gud/gud_pipe.c @@ -205,7 +205,7 @@ static int gud_prep_flush(struct gud_device *gdrm, struct drm_framebuffer *fb, len = gud_xrgb_to_color(buf, format, vaddr, fb, rect); } } else if (gud_is_big_endian() && format->cpp[0] > 1) { - drm_fb_swab(buf, 0, vaddr, fb, rect, !import_attach); + drm_fb_swab(, NULL, map_data, fb, rect, !import_attach); } else if (compression && !import_attach && pitch == fb->pitches[0]) { /* can compress directly from the framebuffer */ buf = vaddr + rect->y1 * pitch; diff --git a/include/drm/drm_format_helper.h b/include/drm/drm_format_helper.h index 8af6a2717bc9..60944feaa936 100644 --- a/include/drm/drm_format_helper.h +++ b/include/drm/drm_format_helper.h @@ -17,9 +17,9 @@ unsigned int drm_fb_clip_offset(unsigned int pitch, const struct
[PATCH 07/12] drm/format-helper: Rework RGB565-to-XRGB8888 conversion
Update RGB565-to-XRGB conversion to support struct iosys_map and convert all users. Although these are single-plane color formats, the new interface supports multi-plane formats for consistency with drm_fb_blit(). Signed-off-by: Thomas Zimmermann --- drivers/gpu/drm/drm_format_helper.c | 25 ++--- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index 4edab44336d8..5ef06f696657 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -430,12 +430,24 @@ static void drm_fb_rgb565_to_xrgb_line(void *dbuf, const void *sbuf, unsigne } } -static void drm_fb_rgb565_to_xrgb_toio(void __iomem *dst, unsigned int dst_pitch, - const void *vaddr, const struct drm_framebuffer *fb, - const struct drm_rect *clip) +static void drm_fb_rgb565_to_xrgb(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *vmap, + const struct drm_framebuffer *fb, + const struct drm_rect *clip) { - drm_fb_xfrm_toio(dst, dst_pitch, 4, vaddr, fb, clip, false, -drm_fb_rgb565_to_xrgb_line); + static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = { + 0, 0, 0, 0 + }; + + if (!dst_pitch) + dst_pitch = default_dst_pitch; + + if (dst[0].is_iomem) + drm_fb_xfrm_toio(dst[0].vaddr_iomem, dst_pitch[0], 4, vmap[0].vaddr, fb, +clip, false, drm_fb_rgb565_to_xrgb_line); + else + drm_fb_xfrm(dst[0].vaddr, dst_pitch[0], 4, vmap[0].vaddr, fb, + clip, false, drm_fb_rgb565_to_xrgb_line); } static void drm_fb_rgb888_to_xrgb_line(void *dbuf, const void *sbuf, unsigned int pixels) @@ -600,8 +612,7 @@ int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t d vmap[0].vaddr, fb, clip); return 0; } else if (fb_format == DRM_FORMAT_RGB565) { - drm_fb_rgb565_to_xrgb_toio(dst[0].vaddr_iomem, dst_pitch[0], - vmap[0].vaddr, fb, clip); + drm_fb_rgb565_to_xrgb(dst, dst_pitch, vmap, fb, clip); return 0; } } else if (dst_format == DRM_FORMAT_XRGB2101010) { -- 2.37.1
[PATCH 05/12] drm/format-helper: Rework XRGB8888-to-RGBG565 conversion
Update XRGB-to-RGB565 conversion to support struct iosys_map and convert all users. Although these are single-plane color formats, the new interface supports multi-plane formats for consistency with drm_fb_blit(). Signed-off-by: Thomas Zimmermann --- drivers/gpu/drm/drm_format_helper.c | 59 +++-- drivers/gpu/drm/drm_mipi_dbi.c | 4 +- drivers/gpu/drm/gud/gud_pipe.c | 3 +- drivers/gpu/drm/tiny/cirrus.c | 3 +- include/drm/drm_format_helper.h | 9 ++--- 5 files changed, 30 insertions(+), 48 deletions(-) diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index 2b5c3746ff4a..8bf5655f5ce0 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -330,9 +330,9 @@ static void drm_fb_xrgb_to_rgb565_swab_line(void *dbuf, const void *sbuf, /** * drm_fb_xrgb_to_rgb565 - Convert XRGB to RGB565 clip buffer - * @dst: RGB565 destination buffer - * @dst_pitch: Number of bytes between two consecutive scanlines within dst - * @vaddr: XRGB source buffer + * @dst: Array of RGB565 destination buffers + * @dst_pitch: Array of numbers of bytes between two consecutive scanlines within dst + * @vmap: Array of XRGB source buffer * @fb: DRM framebuffer * @clip: Clip rectangle area to copy * @swab: Swap bytes @@ -340,43 +340,31 @@ static void drm_fb_xrgb_to_rgb565_swab_line(void *dbuf, const void *sbuf, * Drivers can use this function for RGB565 devices that don't natively * support XRGB. */ -void drm_fb_xrgb_to_rgb565(void *dst, unsigned int dst_pitch, const void *vaddr, - const struct drm_framebuffer *fb, const struct drm_rect *clip, - bool swab) +void drm_fb_xrgb_to_rgb565(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct drm_rect *clip, bool swab) { + static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = { + 0, 0, 0, 0 + }; + void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels); + if (swab) - drm_fb_xfrm(dst, dst_pitch, 2, vaddr, fb, clip, false, - drm_fb_xrgb_to_rgb565_swab_line); + xfrm_line = drm_fb_xrgb_to_rgb565_swab_line; else - drm_fb_xfrm(dst, dst_pitch, 2, vaddr, fb, clip, false, - drm_fb_xrgb_to_rgb565_line); -} -EXPORT_SYMBOL(drm_fb_xrgb_to_rgb565); + xfrm_line = drm_fb_xrgb_to_rgb565_line; -/** - * drm_fb_xrgb_to_rgb565_toio - Convert XRGB to RGB565 clip buffer - * @dst: RGB565 destination buffer (iomem) - * @dst_pitch: Number of bytes between two consecutive scanlines within dst - * @vaddr: XRGB source buffer - * @fb: DRM framebuffer - * @clip: Clip rectangle area to copy - * @swab: Swap bytes - * - * Drivers can use this function for RGB565 devices that don't natively - * support XRGB. - */ -void drm_fb_xrgb_to_rgb565_toio(void __iomem *dst, unsigned int dst_pitch, - const void *vaddr, const struct drm_framebuffer *fb, - const struct drm_rect *clip, bool swab) -{ - if (swab) - drm_fb_xfrm_toio(dst, dst_pitch, 2, vaddr, fb, clip, false, -drm_fb_xrgb_to_rgb565_swab_line); + if (!dst_pitch) + dst_pitch = default_dst_pitch; + + if (dst[0].is_iomem) + drm_fb_xfrm_toio(dst[0].vaddr_iomem, dst_pitch[0], 2, vmap[0].vaddr, fb, clip, +false, xfrm_line); else - drm_fb_xfrm_toio(dst, dst_pitch, 2, vaddr, fb, clip, false, -drm_fb_xrgb_to_rgb565_line); + drm_fb_xfrm(dst[0].vaddr, dst_pitch[0], 2, vmap[0].vaddr, fb, clip, + false, xfrm_line); } -EXPORT_SYMBOL(drm_fb_xrgb_to_rgb565_toio); +EXPORT_SYMBOL(drm_fb_xrgb_to_rgb565); static void drm_fb_xrgb_to_rgb888_line(void *dbuf, const void *sbuf, unsigned int pixels) { @@ -605,8 +593,7 @@ int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t d } else if (dst_format == DRM_FORMAT_RGB565) { if (fb_format == DRM_FORMAT_XRGB) { - drm_fb_xrgb_to_rgb565_toio(dst[0].vaddr_iomem, dst_pitch[0], - vmap[0].vaddr, fb, clip, false); + drm_fb_xrgb_to_rgb565(dst, dst_pitch, vmap, fb, clip, false); return 0; } } else if (dst_format == DRM_FORMAT_RGB888) { diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c index 973a75585cad..d0bdbcb96705 100644
[PATCH 04/12] drm/format-helper: Rework XRGB8888-to-RGBG332 conversion
Update XRGB-to-RGB332 conversion to support struct iosys_map and convert all users. Although these are single-plane color formats, the new interface supports multi-plane formats for consistency with drm_fb_blit(). Signed-off-by: Thomas Zimmermann --- drivers/gpu/drm/drm_format_helper.c | 25 ++- drivers/gpu/drm/gud/gud_pipe.c| 2 +- .../gpu/drm/tests/drm_format_helper_test.c| 14 ++- include/drm/drm_format_helper.h | 5 ++-- 4 files changed, 31 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index fa22d3cb11e8..2b5c3746ff4a 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -265,18 +265,31 @@ static void drm_fb_xrgb_to_rgb332_line(void *dbuf, const void *sbuf, unsigne /** * drm_fb_xrgb_to_rgb332 - Convert XRGB to RGB332 clip buffer - * @dst: RGB332 destination buffer - * @dst_pitch: Number of bytes between two consecutive scanlines within dst - * @src: XRGB source buffer + * @dst: Array of RGB332 destination buffers + * @dst_pitch: Array of numbers of bytes between two consecutive scanlines within dst + * @vmap: Array of XRGB source buffers * @fb: DRM framebuffer * @clip: Clip rectangle area to copy * * Drivers can use this function for RGB332 devices that don't natively support XRGB. */ -void drm_fb_xrgb_to_rgb332(void *dst, unsigned int dst_pitch, const void *src, - const struct drm_framebuffer *fb, const struct drm_rect *clip) +void drm_fb_xrgb_to_rgb332(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct drm_rect *clip) { - drm_fb_xfrm(dst, dst_pitch, 1, src, fb, clip, false, drm_fb_xrgb_to_rgb332_line); + static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = { + 0, 0, 0, 0 + }; + + if (!dst_pitch) + dst_pitch = default_dst_pitch; + + if (dst[0].is_iomem) + drm_fb_xfrm_toio(dst[0].vaddr_iomem, dst_pitch[0], 1, vmap[0].vaddr, fb, clip, +false, drm_fb_xrgb_to_rgb332_line); + else + drm_fb_xfrm(dst[0].vaddr, dst_pitch[0], 1, vmap[0].vaddr, fb, clip, + false, drm_fb_xrgb_to_rgb332_line); } EXPORT_SYMBOL(drm_fb_xrgb_to_rgb332); diff --git a/drivers/gpu/drm/gud/gud_pipe.c b/drivers/gpu/drm/gud/gud_pipe.c index a15cda9ba058..426a3ae6cc50 100644 --- a/drivers/gpu/drm/gud/gud_pipe.c +++ b/drivers/gpu/drm/gud/gud_pipe.c @@ -196,7 +196,7 @@ static int gud_prep_flush(struct gud_device *gdrm, struct drm_framebuffer *fb, } else if (format->format == DRM_FORMAT_R8) { drm_fb_xrgb_to_gray8(buf, 0, vaddr, fb, rect); } else if (format->format == DRM_FORMAT_RGB332) { - drm_fb_xrgb_to_rgb332(buf, 0, vaddr, fb, rect); + drm_fb_xrgb_to_rgb332(, NULL, map_data, fb, rect); } else if (format->format == DRM_FORMAT_RGB565) { drm_fb_xrgb_to_rgb565(buf, 0, vaddr, fb, rect, gud_is_big_endian()); } else if (format->format == DRM_FORMAT_RGB888) { diff --git a/drivers/gpu/drm/tests/drm_format_helper_test.c b/drivers/gpu/drm/tests/drm_format_helper_test.c index 98583bf56044..b74dba06f704 100644 --- a/drivers/gpu/drm/tests/drm_format_helper_test.c +++ b/drivers/gpu/drm/tests/drm_format_helper_test.c @@ -124,7 +124,8 @@ static void xrgb_to_rgb332_test(struct kunit *test) { const struct xrgb_to_rgb332_case *params = test->param_value; size_t dst_size; - __u8 *dst = NULL; + struct iosys_map dst, xrgb; + __u8 *buf = NULL; struct drm_framebuffer fb = { .format = drm_format_info(DRM_FORMAT_XRGB), @@ -135,12 +136,13 @@ static void xrgb_to_rgb332_test(struct kunit *test) >clip); KUNIT_ASSERT_GT(test, dst_size, 0); - dst = kunit_kzalloc(test, dst_size, GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dst); + buf = kunit_kzalloc(test, dst_size, GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf); - drm_fb_xrgb_to_rgb332(dst, params->dst_pitch, params->xrgb, - , >clip); - KUNIT_EXPECT_EQ(test, memcmp(dst, params->expected, dst_size), 0); + iosys_map_set_vaddr(, buf); + iosys_map_set_vaddr(, (void __force *)params->xrgb); + drm_fb_xrgb_to_rgb332(, >dst_pitch, , , >clip); + KUNIT_EXPECT_EQ(test, memcmp(buf, params->expected, dst_size), 0); } static struct kunit_case drm_format_helper_test_cases[] = { diff --git
[PATCH 02/12] drm/format-helper: Merge drm_fb_memcpy() and drm_fb_memcpy_toio()
Merge drm_fb_memcpy() and drm_fb_memcpy() into drm_fb_memcpy() that uses struct iosys_map for buffers. The new function also supports multi-plane color formats. Convert all users of the original helpers. Signed-off-by: Thomas Zimmermann --- drivers/gpu/drm/drm_format_helper.c | 77 + drivers/gpu/drm/drm_mipi_dbi.c | 3 +- drivers/gpu/drm/gud/gud_pipe.c | 4 +- drivers/gpu/drm/hyperv/hyperv_drm_modeset.c | 11 +-- drivers/gpu/drm/mgag200/mgag200_mode.c | 11 +-- drivers/gpu/drm/tiny/cirrus.c | 21 +++--- include/drm/drm_format_helper.h | 7 +- 7 files changed, 63 insertions(+), 71 deletions(-) diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index 4d74d46ab155..49589b442f18 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -131,63 +131,48 @@ static int drm_fb_xfrm_toio(void __iomem *dst, unsigned long dst_pitch, unsigned /** * drm_fb_memcpy - Copy clip buffer - * @dst: Destination buffer - * @dst_pitch: Number of bytes between two consecutive scanlines within dst - * @vaddr: Source buffer + * @dst: Array of destination buffers + * @dst_pitch: Array of numbers of bytes between two consecutive scanlines within dst + * @vmap: Array of source buffers * @fb: DRM framebuffer * @clip: Clip rectangle area to copy * * This function does not apply clipping on dst, i.e. the destination * is at the top-left corner. */ -void drm_fb_memcpy(void *dst, unsigned int dst_pitch, const void *vaddr, - const struct drm_framebuffer *fb, const struct drm_rect *clip) +void drm_fb_memcpy(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct drm_rect *clip) { - unsigned int cpp = fb->format->cpp[0]; - size_t len = (clip->x2 - clip->x1) * cpp; - unsigned int y, lines = clip->y2 - clip->y1; - - if (!dst_pitch) - dst_pitch = len; + static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = { + 0, 0, 0, 0 + }; - vaddr += clip_offset(clip, fb->pitches[0], cpp); - for (y = 0; y < lines; y++) { - memcpy(dst, vaddr, len); - vaddr += fb->pitches[0]; - dst += dst_pitch; - } -} -EXPORT_SYMBOL(drm_fb_memcpy); - -/** - * drm_fb_memcpy_toio - Copy clip buffer - * @dst: Destination buffer (iomem) - * @dst_pitch: Number of bytes between two consecutive scanlines within dst - * @vaddr: Source buffer - * @fb: DRM framebuffer - * @clip: Clip rectangle area to copy - * - * This function does not apply clipping on dst, i.e. the destination - * is at the top-left corner. - */ -void drm_fb_memcpy_toio(void __iomem *dst, unsigned int dst_pitch, const void *vaddr, - const struct drm_framebuffer *fb, const struct drm_rect *clip) -{ - unsigned int cpp = fb->format->cpp[0]; - size_t len = (clip->x2 - clip->x1) * cpp; - unsigned int y, lines = clip->y2 - clip->y1; + const struct drm_format_info *format = fb->format; + unsigned int i, y, lines = drm_rect_height(clip); if (!dst_pitch) - dst_pitch = len; - - vaddr += clip_offset(clip, fb->pitches[0], cpp); - for (y = 0; y < lines; y++) { - memcpy_toio(dst, vaddr, len); - vaddr += fb->pitches[0]; - dst += dst_pitch; + dst_pitch = default_dst_pitch; + + for (i = 0; i < format->num_planes; ++i) { + unsigned int cpp_i = format->cpp[i]; + size_t len_i = drm_rect_width(clip) * cpp_i; + unsigned int dst_pitch_i = dst_pitch[i]; + struct iosys_map dst_i = dst[i]; + struct iosys_map vmap_i = vmap[i]; + + if (!dst_pitch_i) + dst_pitch_i = len_i; + + iosys_map_incr(_i, clip_offset(clip, fb->pitches[i], cpp_i)); + for (y = 0; y < lines; y++) { + iosys_map_memcpy_to(_i, 0, vmap_i.vaddr, len_i); + iosys_map_incr(_i, fb->pitches[i]); + iosys_map_incr(_i, dst_pitch_i); + } } } -EXPORT_SYMBOL(drm_fb_memcpy_toio); +EXPORT_SYMBOL(drm_fb_memcpy); static void drm_fb_swab16_line(void *dbuf, const void *sbuf, unsigned int pixels) { @@ -584,7 +569,7 @@ int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t d dst_format = DRM_FORMAT_XRGB2101010; if (dst_format == fb_format) { - drm_fb_memcpy_toio(dst[0].vaddr_iomem, dst_pitch[0], vmap[0].vaddr, fb, clip); + drm_fb_memcpy(dst, dst_pitch, vmap, fb, clip); return 0; } else if (dst_format == DRM_FORMAT_RGB565) { diff --git a/drivers/gpu/drm/drm_mipi_dbi.c
[PATCH 00/12] drm/format-helper: Move to struct iosys_map
Change format-conversion helpers to use struct iosys_map for source and destination buffers. Update all users. Also prepare interface for multi-plane color formats. The format-conversion helpers mostly used to convert to I/O memory or system memory. To actual memory type depended on the usecase. We now have drivers upcomming that do the conversion entirely in system memory. It's a good opportunity to stream-line the interface of the conversion helpers to use struct iosys_map. Source and destination buffers can now be either in system or in I/O memory. Note that the implementation still only supports source buffers in system memory. This patchset also changes the interface to support multi-plane color formats, where the values for each component are stored in distinct memory locations. Converting from RGBRGBRGB to RRRGGGBBB would require a single source buffer with RGB values and 3 destination buffers for the R, G and B values. Conversion-helper interfaces now support this. Thomas Zimmermann (12): drm/format-helper: Provide drm_fb_blit() drm/format-helper: Merge drm_fb_memcpy() and drm_fb_memcpy_toio() drm/format-helper: Convert drm_fb_swab() to struct iosys_map drm/format-helper: Rework XRGB-to-RGBG332 conversion drm/format-helper: Rework XRGB-to-RGBG565 conversion drm/format-helper: Rework XRGB-to-RGB888 conversion drm/format-helper: Rework RGB565-to-XRGB conversion drm/format-helper: Rework RGB888-to-XRGB conversion drm/format-helper: Rework XRGB-to-XRGB2101010 conversion drm/format-helper: Rework XRGB-to-GRAY8 conversion drm/format-helper: Rework XRGB-to-MONO conversion drm/format-helper: Move destination-buffer handling into internal helper drivers/gpu/drm/drm_format_helper.c | 379 +- drivers/gpu/drm/drm_mipi_dbi.c| 9 +- drivers/gpu/drm/gud/gud_pipe.c| 20 +- drivers/gpu/drm/hyperv/hyperv_drm_modeset.c | 11 +- drivers/gpu/drm/mgag200/mgag200_mode.c| 11 +- drivers/gpu/drm/solomon/ssd130x.c | 7 +- .../gpu/drm/tests/drm_format_helper_test.c| 14 +- drivers/gpu/drm/tiny/cirrus.c | 19 +- drivers/gpu/drm/tiny/repaper.c| 6 +- drivers/gpu/drm/tiny/simpledrm.c | 18 +- drivers/gpu/drm/tiny/st7586.c | 5 +- include/drm/drm_format_helper.h | 56 ++- 12 files changed, 294 insertions(+), 261 deletions(-) base-commit: 15fbed4f822211fbb7653c2b8591594d92de9551 prerequisite-patch-id: c2b2f08f0eccc9f5df0c0da49fa1d36267deb11d prerequisite-patch-id: c67e5d886a47b7d0266d81100837557fda34cb24 prerequisite-patch-id: 3f204510fcbf9530d6540bd8e6128cce598988b6 -- 2.37.1
[PATCH 01/12] drm/format-helper: Provide drm_fb_blit()
Provide drm_fb_blit() that works with struct iosys_map. Update all users of drm_fb_blit_toio(), which required a destination buffer in I/O memory. The new function's interface works with multi-plane color formats, although the implementation only supports a single plane for now. Signed-off-by: Thomas Zimmermann --- drivers/gpu/drm/drm_format_helper.c | 39 ++--- drivers/gpu/drm/tiny/simpledrm.c| 18 +++-- include/drm/drm_format_helper.h | 7 +++--- 3 files changed, 38 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index c6182b5de78b..4d74d46ab155 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -8,9 +8,10 @@ * (at your option) any later version. */ +#include +#include #include #include -#include #include #include @@ -545,9 +546,9 @@ void drm_fb_xrgb_to_gray8(void *dst, unsigned int dst_pitch, const void *vad EXPORT_SYMBOL(drm_fb_xrgb_to_gray8); /** - * drm_fb_blit_toio - Copy parts of a framebuffer to display memory - * @dst: The display memory to copy to - * @dst_pitch: Number of bytes between two consecutive scanlines within dst + * drm_fb_blit - Copy parts of a framebuffer to display memory + * @dst: Array of display-memory addresses to copy to + * @dst_pitch: Array of numbers of bytes between two consecutive scanlines within dst * @dst_format:FOURCC code of the display's color format * @vmap: The framebuffer memory to copy from * @fb:The framebuffer to copy from @@ -557,14 +558,18 @@ EXPORT_SYMBOL(drm_fb_xrgb_to_gray8); * formats of the display and the framebuffer mismatch, the blit function * will attempt to convert between them. * + * The parameters @dst, @dst_pitch and @vmap refer to arrays. Each array must + * have at least as many entries as there are planes in @dst_format's format. Each + * entry stores the value for the format's respective color plane at the same index. + * * Returns: * 0 on success, or * -EINVAL if the color-format conversion failed, or * a negative error code otherwise. */ -int drm_fb_blit_toio(void __iomem *dst, unsigned int dst_pitch, uint32_t dst_format, -const void *vmap, const struct drm_framebuffer *fb, -const struct drm_rect *clip) +int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t dst_format, + const struct iosys_map *vmap, const struct drm_framebuffer *fb, + const struct drm_rect *clip) { uint32_t fb_format = fb->format->format; @@ -579,30 +584,35 @@ int drm_fb_blit_toio(void __iomem *dst, unsigned int dst_pitch, uint32_t dst_for dst_format = DRM_FORMAT_XRGB2101010; if (dst_format == fb_format) { - drm_fb_memcpy_toio(dst, dst_pitch, vmap, fb, clip); + drm_fb_memcpy_toio(dst[0].vaddr_iomem, dst_pitch[0], vmap[0].vaddr, fb, clip); return 0; } else if (dst_format == DRM_FORMAT_RGB565) { if (fb_format == DRM_FORMAT_XRGB) { - drm_fb_xrgb_to_rgb565_toio(dst, dst_pitch, vmap, fb, clip, false); + drm_fb_xrgb_to_rgb565_toio(dst[0].vaddr_iomem, dst_pitch[0], + vmap[0].vaddr, fb, clip, false); return 0; } } else if (dst_format == DRM_FORMAT_RGB888) { if (fb_format == DRM_FORMAT_XRGB) { - drm_fb_xrgb_to_rgb888_toio(dst, dst_pitch, vmap, fb, clip); + drm_fb_xrgb_to_rgb888_toio(dst[0].vaddr_iomem, dst_pitch[0], + vmap[0].vaddr, fb, clip); return 0; } } else if (dst_format == DRM_FORMAT_XRGB) { if (fb_format == DRM_FORMAT_RGB888) { - drm_fb_rgb888_to_xrgb_toio(dst, dst_pitch, vmap, fb, clip); + drm_fb_rgb888_to_xrgb_toio(dst[0].vaddr_iomem, dst_pitch[0], + vmap[0].vaddr, fb, clip); return 0; } else if (fb_format == DRM_FORMAT_RGB565) { - drm_fb_rgb565_to_xrgb_toio(dst, dst_pitch, vmap, fb, clip); + drm_fb_rgb565_to_xrgb_toio(dst[0].vaddr_iomem, dst_pitch[0], + vmap[0].vaddr, fb, clip); return 0; } } else if (dst_format == DRM_FORMAT_XRGB2101010) { if (fb_format == DRM_FORMAT_XRGB) { - drm_fb_xrgb_to_xrgb2101010_toio(dst, dst_pitch, vmap, fb, clip); + drm_fb_xrgb_to_xrgb2101010_toio(dst[0].vaddr_iomem,
Re: [PATCH 2/4] arm64: dts: qcom: add sdm845-google-blueline (Pixel 3)
n Tue, 19 Jul 2022 at 03:43, Dmitry Baryshkov wrote: > > On 19/07/2022 00:30, Caleb Connolly wrote: > > From: Amit Pundir > > > > This adds an initial dts for the Blueline (Pixel 3). Supported > > functionality includes display, Debug UART, UFS, USB-C (peripheral), WiFi, > > Bluetooth and modem. > > > > Bootloader compatible board and msm IDs are needed for the kernel to boot > > with Pixel3 bootloader, so those are added. > > > > GPIOs 0 through 3 and 81 through 84 are configured to not be accessible > > from the application CPUs, so we mark them as reserved to allow the Pixel 3 > > to boot. > > > > The reserved-memory locations where obtained from downstream using > > kernel logs: > > https://gist.github.com/calebccff/090d10bfac3cb9e9bd98dda30b054c96 > > > > The rmtfs region is allocated with UIO, making it technically "dynamic". > > It's address and size can be read from sysfs: > > > > blueline:/ # cat /sys/class/uio/uio0/name > > rmtfs > > at /sys/class/uio/uio0/maps/map0/addr > > 0xf2701000 > > blueline:/ # cat /sys/class/uio/uio0/maps/map0/size > > 0x0020 > > > > Like the OnePlus 6, it needs 1kB reserved on either side of the rmtfs > > memory to workaround some XPU bug which would otherwise cause erroneous > > XPU violations when accessing the rmtfs_mem region. > > > > For wifi, the pixel 3 reports a board-id of 0xFF, and downstream > > only includes a single bdwlan file. The qcom,ath10k-calibration-variant > > property is set to ensure that the correct calibration data is used. > > > > Signed-off-by: Bjorn Andersson > > [AmitP: Cherry-picked and refactored from Bjorn's db845c dts > > ("arm64: dts: qcom: Add Dragonboard 845c") > > https://lkml.org/lkml/2019/6/6/7] > > Signed-off-by: Amit Pundir > > [sumits: merged commits to add board and msm ids, gpio range reservation, > >ufs device-reset gpio and adaptation to v5.5+ changes] > > Signed-off-by: Sumit Semwal > > [vinod: Add display nodes] > > Signed-off-by: Vinod Koul > > [caleb: remove db845c bits, cleanup, add reserved-memory for modem/wifi] > > Signed-off-by: Caleb Connolly > > Thanks for your patch, few minor items to improve. > > > --- > > arch/arm64/boot/dts/qcom/Makefile | 1 + > > .../boot/dts/qcom/sdm845-google-blueline.dts | 652 ++ > > 2 files changed, 653 insertions(+) > > create mode 100644 arch/arm64/boot/dts/qcom/sdm845-google-blueline.dts > > > > diff --git a/arch/arm64/boot/dts/qcom/Makefile > > b/arch/arm64/boot/dts/qcom/Makefile > > index 2f8aec2cc6db..c151e17e6eb7 100644 > > --- a/arch/arm64/boot/dts/qcom/Makefile > > +++ b/arch/arm64/boot/dts/qcom/Makefile > > @@ -100,6 +100,7 @@ dtb-$(CONFIG_ARCH_QCOM) += sdm845-cheza-r1.dtb > > dtb-$(CONFIG_ARCH_QCOM) += sdm845-cheza-r2.dtb > > dtb-$(CONFIG_ARCH_QCOM) += sdm845-cheza-r3.dtb > > dtb-$(CONFIG_ARCH_QCOM) += sdm845-db845c.dtb > > +dtb-$(CONFIG_ARCH_QCOM) += sdm845-google-blueline.dtb > > dtb-$(CONFIG_ARCH_QCOM) += sdm845-mtp.dtb > > dtb-$(CONFIG_ARCH_QCOM) += sdm845-oneplus-enchilada.dtb > > dtb-$(CONFIG_ARCH_QCOM) += sdm845-oneplus-fajita.dtb > > diff --git a/arch/arm64/boot/dts/qcom/sdm845-google-blueline.dts > > b/arch/arm64/boot/dts/qcom/sdm845-google-blueline.dts > > new file mode 100644 > > index ..dec979ad9209 > > --- /dev/null > > +++ b/arch/arm64/boot/dts/qcom/sdm845-google-blueline.dts > > @@ -0,0 +1,652 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > + > > +/dts-v1/; > > + > > +#include > > +#include > > +#include > > +#include > > + > > +#include "sdm845.dtsi" > > +#include "pm8998.dtsi" > > +#include "pmi8998.dtsi" > > + > > +/delete-node/ _region; > > +/delete-node/ _mem; > > +/delete-node/ _mem; > > +/delete-node/ _region; > > +/delete-node/ _mem; > > +/delete-node/ _mem; > > +/delete-node/ _mem; > > + > > +/ { > > + model = "Google Pixel 3"; > > + compatible = "google,blueline", "qcom,sdm845"; > > + qcom,board-id = <0x00021505 0>; > > + qcom,msm-id = <321 0x20001>; > > + > > + aliases { > > + serial0 = > > + serial1 = > > + }; > > + > > + chosen { > > + stdout-path = "serial0:115200n8"; > > + }; > > + > > + volume-keys { > > + compatible = "gpio-keys"; > > + label = "Volume keys"; > > + autorepeat; > > + > > + pinctrl-names = "default"; > > + pinctrl-0 = <_up_gpio>; > > + > > + vol-up { > > + label = "Volume Up"; > > + linux,code = ; > > + gpios = <_gpio 6 GPIO_ACTIVE_LOW>; > > + debounce-interval = <15>; > > + }; > > + }; > > + > > + reserved-memory { > > + #address-cells = <2>; > > + #size-cells = <2>; > > + ranges; > > These properties are already part of the sdm845.dtsi, so no need to have > them here. > > > + > > + mpss_region:
Re: [PATCH] drm: lcdif: change burst size to 256B
On 7/27/22 05:56, Marco Felsch wrote: Hi Marek, Liu, Hi, On 22-07-26, Liu Ying wrote: On Tue, 2022-07-26 at 16:19 +0200, Marek Vasut wrote: On 7/26/22 11:43, Marco Felsch wrote: FIFO underruns are seen if a AXI bus master with a higher priority do a lot of memory access. Increase the burst size to 256B to avoid such underruns and to improve the memory access efficiency. Sigh, this again ... I know.. we also tried the PANIC mode but this somehow didn't worked as documented. So this was the only way to reduce the underruns without adapting the interconnect prio for the hdmi-lcdif. Right, the PANIC watermark didn't work on mxsfb for me either when it came to FIFO underruns. [...] +* are two known values: +* 1 - 128Byte +* 2 - 256Byte +* +* Downstream has set the burst size to 256Byte to improve the memory +* efficiency so set it here too. This also reduces the FIFO underrun +* possibility. +*/ + ctrl = CTRLDESCL0_3_P_SIZE(2) | CTRLDESCL0_3_T_SIZE(2) | + CTRLDESCL0_3_PITCH(lcdif->crtc.primary->state->fb- pitches[0]); + writel(ctrl, lcdif->base + LCDC_V8_CTRLDESCL0_3); Nit: I would write the register directly, instead of caching the value in ctrl. IMHO it's more readable that way. I agree, and we can also add to the variable in case there are more undocumented bits.
Re: [Intel-gfx] [PATCH v5 1/7] drm: Move and add a few utility macros into drm util header
Hi, On Mon, Jul 25, 2022 at 12:25:22PM +0300, Gwan-gyeong Mun wrote: > It moves overflows_type utility macro into drm util header from i915_utils > header. The overflows_type can be used to catch the truncation between data > types. And it adds safe_conversion() macro which performs a type conversion > (cast) of an source value into a new variable, checking that the > destination is large enough to hold the source value. > And it adds exact_type and exactly_pgoff_t macro to catch type mis-match > while compiling. > > v3: Add is_type_unsigned() macro (Mauro) > Modify overflows_type() macro to consider signed data types (Mauro) > Fix the problem that safe_conversion() macro always returns true > v4: Fix kernel-doc markups > > Signed-off-by: Gwan-gyeong Mun > Cc: Thomas Hellström > Cc: Matthew Auld > Cc: Nirmoy Das > Cc: Jani Nikula > Reviewed-by: Mauro Carvalho Chehab > --- > drivers/gpu/drm/i915/i915_utils.h | 5 +- > include/drm/drm_util.h| 77 +++ > 2 files changed, 78 insertions(+), 4 deletions(-) Jani and Mauro suggested to have this macro in include/drm/drm_util.h. Can I please have an ack from one of the drm maintainers so that I can go ahead an apply this series? Thanks, Andi > > diff --git a/drivers/gpu/drm/i915/i915_utils.h > b/drivers/gpu/drm/i915/i915_utils.h > index c10d68cdc3ca..345e5b2dc1cd 100644 > --- a/drivers/gpu/drm/i915/i915_utils.h > +++ b/drivers/gpu/drm/i915/i915_utils.h > @@ -32,6 +32,7 @@ > #include > #include > #include > +#include > > #ifdef CONFIG_X86 > #include > @@ -111,10 +112,6 @@ bool i915_error_injected(void); > #define range_overflows_end_t(type, start, size, max) \ > range_overflows_end((type)(start), (type)(size), (type)(max)) > > -/* Note we don't consider signbits :| */ > -#define overflows_type(x, T) \ > - (sizeof(x) > sizeof(T) && (x) >> BITS_PER_TYPE(T)) > - > #define ptr_mask_bits(ptr, n) ({ \ > unsigned long __v = (unsigned long)(ptr); \ > (typeof(ptr))(__v & -BIT(n)); \ > diff --git a/include/drm/drm_util.h b/include/drm/drm_util.h > index 79952d8c4bba..1de9ee5704fa 100644 > --- a/include/drm/drm_util.h > +++ b/include/drm/drm_util.h > @@ -62,6 +62,83 @@ > */ > #define for_each_if(condition) if (!(condition)) {} else > > +/** > + * is_type_unsigned - helper for checking data type which is an unsigned data > + * type or not > + * @x: The data type to check > + * > + * Returns: > + * True if the data type is an unsigned data type, false otherwise. > + */ > +#define is_type_unsigned(x) ((typeof(x))-1 >= (typeof(x))0) > + > +/** > + * overflows_type - helper for checking the truncation between data types > + * @x: Source for overflow type comparison > + * @T: Destination for overflow type comparison > + * > + * It compares the values and size of each data type between the first and > + * second argument to check whether truncation can occur when assigning the > + * first argument to the variable of the second argument. > + * Source and Destination can be used with or without sign bit. > + * Composite data structures such as union and structure are not considered. > + * Enum data types are not considered. > + * Floating point data types are not considered. > + * > + * Returns: > + * True if truncation can occur, false otherwise. > + */ > + > +#define overflows_type(x, T) \ > + (is_type_unsigned(x) ? \ > + is_type_unsigned(T) ? \ > + (sizeof(x) > sizeof(T) && (x) >> BITS_PER_TYPE(T)) ? 1 > : 0 \ > + : (sizeof(x) >= sizeof(T) && (x) >> (BITS_PER_TYPE(T) - > 1)) ? 1 : 0 \ > + : is_type_unsigned(T) ? \ > + ((x) < 0) ? 1 : (sizeof(x) > sizeof(T) && (x) >> > BITS_PER_TYPE(T)) ? 1 : 0 \ > + : (sizeof(x) > sizeof(T)) ? \ > + ((x) < 0) ? (((x) * -1) >> BITS_PER_TYPE(T)) ? 1 : 0 \ > + : ((x) >> BITS_PER_TYPE(T)) ? 1 : 0 \ > + : 0) > + > +/** > + * exact_type - break compile if source type and destination value's type are > + * not the same > + * @T: Source type > + * @n: Destination value > + * > + * It is a helper macro for a poor man's -Wconversion: only allow variables > of > + * an exact type. It determines whether the source type and destination > value's > + * type are the same while compiling, and it breaks compile if two types are > + * not the same > + */ > +#define exact_type(T, n) \ > + BUILD_BUG_ON(!__builtin_constant_p(n) && > !__builtin_types_compatible_p(T, typeof(n))) > + > +/** > + * exactly_pgoff_t - helper to check if the type of a value is pgoff_t > + * @n: value to compare pgoff_t type > + * > + * It breaks compile if the argument value's type is not pgoff_t type. > + */ > +#define exactly_pgoff_t(n) exact_type(pgoff_t, n) > + > +/** > + * safe_conversion - perform a type conversion (cast) of an
Re: [PATCH v3 1/2] dt-bindings: display: panel: Add Novatek NT35596S panel bindings
On 26/07/2022 12:15, Molly Sophia wrote: > Add documentation for "novatek,nt35596s" panel. > > Changes in v3: > - Embed the documentation into existing one (novatek,nt36672a). > > Signed-off-by: Molly Sophia > --- > .../display/panel/novatek,nt36672a.yaml | 20 --- > 1 file changed, 13 insertions(+), 7 deletions(-) > > diff --git > a/Documentation/devicetree/bindings/display/panel/novatek,nt36672a.yaml > b/Documentation/devicetree/bindings/display/panel/novatek,nt36672a.yaml > index 563766d283f6..560fb66d0e5a 100644 > --- a/Documentation/devicetree/bindings/display/panel/novatek,nt36672a.yaml > +++ b/Documentation/devicetree/bindings/display/panel/novatek,nt36672a.yaml > @@ -20,14 +20,20 @@ allOf: > > properties: >compatible: > -items: > - - enum: > - - tianma,fhd-video > - - const: novatek,nt36672a > +oneOf: > + - items: > + - enum: > + - tianma,fhd-video > + - const: novatek,nt36672a > + > + - items: > + - enum: > + - jdi,fhd-nt35596s > + - const: novatek,nt35596s This entire entry should be rather before nt36672a judging by numbers: +oneOf: + - items: + - enum: + - jdi,fhd-nt35596s + - const: novatek,nt35596s + + - items: + - enum: + - tianma,fhd-video + - const: novatek,nt36672a Best regards, Krzysztof
Re: [PATCH v6 11/13] leds: rgb: mt6370: Add MediaTek MT6370 current sink type LED Indicator support
On Wed, Jul 27, 2022 at 9:37 AM ChiaEn Wu wrote: > On Tue, Jul 26, 2022 at 8:18 PM Andy Shevchenko > wrote: > > ... > > > > Just for saving memory space. > > > Because these led_classdevs do not be used at the same time. > > > Or do you think it would be better to rewrite it as follows? > > > - > > > struct mt6370_led { > > >struct led_classdev isink; > > >struct led_classdev_mc mc; > > >struct mt6370_priv *priv; > > >u32 default_state; > > >u32 index; > > > }; > > > - > > > > You obviously didn't get what I'm talking about... > > Each union to work properly should have an associated variable that > > holds the information of which field of the union is in use. Do you > > have such a variable? If not, how does your code know which one to > > use? If yes, add a proper comment there. > > > > Ummm... from my understanding, > if the colors of these four LEDs are set to 'LED_COLOR_ID_RGB' or > 'LED_COLOR_ID_MULTI' in DT, > their 'led->index' will be set to 'MT6370_VIRTUAL_MULTICOLOR' in > 'mt6370_leds_probe()'. > If so, these led devices will be set as 'struct led_classdev_mc' and > use related ops functions in 'mt6370_init_led_properties()'. > Instead, they whose 'led->index' is not 'MT6370_VIRTUAL_MULTICOLOR' > will be set as 'struct led_classdev'. > So, maybe the member 'index' of the 'struct mt6370_led' is what you > describe the information of which field of the union is in use? >From this description it sounds like it is. > I will add the proper comment here to describe this thing. I'm so > sorry for misunderstanding your mean last time. Yes, please add a compressed version of what you said above to the code. -- With Best Regards, Andy Shevchenko
Re: [PATCH v2 10/10] drm/ofdrm: Support color management
On 7/27/22 10:41, Thomas Zimmermann wrote: [...] >> >>> +static void __iomem *ofdrm_mach64_cmap_ioremap(struct ofdrm_device *odev, >>> + struct device_node *of_node, >>> + u64 fb_base) >>> +{ >>> + struct drm_device *dev = >dev; >>> + u64 address; >>> + void __iomem *cmap_base; >>> + >>> + address = fb_base & 0xff00ul; >>> + address += 0x7ff000; >>> + >> >> It would be good to know where these addresses are coming from. Maybe some >> constant macros or a comment ? Same for the other places where addresses >> and offsets are used. > > I have no idea where these values come from. I took them from offb. And > I suspect that some of these CMAP helpers could be further merged if > only it was clear where the numbers come from. But as i don't have the > equipment for testing, I took most of this literally as-is from offb. > I see. As Michal mentioned maybe someone more familiar with this platform could shed some light about these but in any case that could be done later. [...] >>> + >>> + new_crtc_state = drm_atomic_get_new_crtc_state(new_state, >>> new_plane_state->crtc); >>> + >>> + new_ofdrm_crtc_state = to_ofdrm_crtc_state(new_crtc_state); >>> + new_ofdrm_crtc_state->format = new_fb->format; >>> + >> >> Ah, I understand now why you didn't factor out the .atomic_check callbacks >> for the two drivers in a fwfb helper. Maybe you can also add a comment to >> mention that this updates the format so the CRTC palette can be applied in >> the .atomic_flush callback ? > > Yeah, this code is one reason for not sharing atomic_check in fwfb. The > other reason is that the fwfb code is only a wrapper around the atomic > helpers with little extra value. I did have such fwfb helpers a some > point, but removed them. > Got it. -- Best regards, Javier Martinez Canillas Linux Engineering Red Hat
Re: [PATCH v15 07/11] drm/mediatek: Add retry to prevent misjudgment for sink devices
Il 27/07/22 06:50, Bo-Chen Chen ha scritto: For some DP dungles, we need to train more than onece to confirm that we don't misjudge the status of sink device. Please fix the typos in your commit title and description. title: misjudgment -> misjudgement desc: dungles->dongles; onece->once Signed-off-by: Bo-Chen Chen --- drivers/gpu/drm/mediatek/mtk_dp.c | 21 ++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c index ce817cb59445..80d7d6488105 100644 --- a/drivers/gpu/drm/mediatek/mtk_dp.c +++ b/drivers/gpu/drm/mediatek/mtk_dp.c @@ -42,6 +42,7 @@ #define MTK_DP_CHECK_SINK_CAP_TIMEOUT_COUNT 3 #define MTK_DP_TBC_BUF_READ_START_ADDR 0x08 #define MTK_DP_TRAIN_DOWNSCALE_RETRY 8 +#define MTK_DP_TRAIN_CLEAR_RETRY 50 struct mtk_dp_train_info { bool tps3; @@ -1431,11 +1432,25 @@ static int mtk_dp_video_config(struct mtk_dp *mtk_dp) static int mtk_dp_training(struct mtk_dp *mtk_dp) { + short max_retry = MTK_DP_TRAIN_CLEAR_RETRY; int ret; - ret = mtk_dp_train_start(mtk_dp); - if (ret) - return ret; + /* +* We do retry to confirm that we don't misjudge the sink status. +* If it is still failed, we can confirm there are some issues for the +* sink device. +*/ + do { + ret = mtk_dp_train_start(mtk_dp); + if (!ret) + break; + } while (--max_retry); + + dev_info(mtk_dp->dev, "dp training clear retry times: %d\n", +MTK_DP_TRAIN_CLEAR_RETRY - max_retry); dev_dbg() here. ...after which, Reviewed-by: AngeloGioacchino Del Regno + + if (!max_retry) + return -ETIMEDOUT; ret = mtk_dp_video_config(mtk_dp); if (ret)
Re: [PATCH v2 06/10] drm/simpledrm: Move some functionality into fwfb helper library
On 7/27/22 10:24, Thomas Zimmermann wrote: > Hi > > Am 25.07.22 um 18:23 schrieb Javier Martinez Canillas: >> On 7/20/22 16:27, Thomas Zimmermann wrote: >>> Move some of simpledrm's functionality into a helper library. Other >>> drivers for firmware-provided framebuffers will also need functions >>> to handle fixed modes and color formats, or update the back buffer. >>> >>> Signed-off-by: Thomas Zimmermann >>> --- >> >> Nice patch! > > TBH it took me 3 tries to get something done for this library and I'm > still not happy with the result. I want to share code between simpledrm > and ofdrm, but that turns out to be harder then expected. A good part of > this code appears to belong into other libraries (you also mentioned > this below). > > I don't want to duplicated code between simpledrm and ofdrm without > reason, but I expect that this library will somewhen be refactored and > dissolved into existing libraries. > Yes, I think is a step in the right direction and guess it would be even more useful once/if a 3rd firmware-provided framebuffer driver is added. > >> >> [...] >> >>> + >>> +/** >>> + * DOC: overview >>> + * >>> + * The Firmware Framebuffer library FWFB provides helpers for devices with >>> + * fixed-mode backing storage. It helps drivers to export a display mode of >>> + * te correct size and copy updates to the backing storage. >> >> the >> >> it is "backing storage" or "backing store" ? I always thought that storage >> was >> used for non-volatile media while "store" could be volatile and non-volatile. > > Why store? Isn't that a little shop for fashion or groceries? I'm no > native speaker; I can't tell if either implies that we're sending > pictures to a warehouse or bakery. :) > LOL. > Would 'back buffer' (in contrast to 'shadow buffer') be clear? > Back buffer is more clear indeed. [...] >> It seems a little bit arbitrary to me that format is the only field that's >> a pointer and the other ones are embedded into the struct drm_fwfb. Any >> reason for that or is just a consequence of how types were used by the >> simpledrm_device_create() function before that code moved into helpers ? > > Format is constant and comes from statically initialized memory in > drm_fourcc.c. I'd expect to be able to compare formats by comparing the > pointers. Copying the format here would break the assumption. > I see. Makes sense. >> >> [...] >> >>> +static bool is_listed_fourcc(const uint32_t *fourccs, size_t nfourccs, >>> uint32_t fourcc) >>> +{ >>> + const uint32_t *fourccs_end = fourccs + nfourccs; >>> + >>> + while (fourccs < fourccs_end) { >>> + if (*fourccs == fourcc) >>> + return true; >>> + ++fourccs; >>> + } >>> + return false; >>> +} >> >> This seems a helper that could be useful besides the drm_fwfb_helper.c file. >> >> I believe patches 1-6 shouldn't wait for the others in this series and could >> just be merged when ready. Patches 7-10 can follow later. > > Yeah, I'd like to move patches 1 to 5 into a new series for merging. > Patch 6 is only useful for ofdrm and as I said, maybe there's a better > solution then this library. I'd rather keep it here for now. > OK. -- Best regards, Javier Martinez Canillas Linux Engineering Red Hat
Re: [PATCH v15 06/11] drm/mediatek: Add MT8195 External DisplayPort support
Il 27/07/22 06:50, Bo-Chen Chen ha scritto: From: Guillaume Ranquet This patch adds External DisplayPort support to the mt8195 eDP driver. Signed-off-by: Guillaume Ranquet Signed-off-by: Bo-Chen Chen Reviewed-by: AngeloGioacchino Del Regno
Re: [PATCH v15 05/11] drm/mediatek: Add MT8195 Embedded DisplayPort driver
Il 27/07/22 06:50, Bo-Chen Chen ha scritto: From: Markus Schneider-Pargmann This patch adds a embedded displayport driver for the MediaTek mt8195 SoC. It supports the MT8195, the embedded DisplayPort units. It offers DisplayPort 1.4 with up to 4 lanes. The driver creates a child device for the phy. The child device will never exist without the parent being active. As they are sharing a register range, the parent passes a regmap pointer to the child so that both can work with the same register range. The phy driver sets device data that is read by the parent to get the phy device that can be used to control the phy properties. This driver is based on an initial version by Jitao shi Signed-off-by: Markus Schneider-Pargmann Signed-off-by: Guillaume Ranquet Signed-off-by: Bo-Chen Chen Tested-by: AngeloGioacchino Del Regno Reviewed-by: AngeloGioacchino Del Regno
Re: [PATCH v15 04/11] video/hdmi: Add audio_infoframe packing for DP
Il 27/07/22 06:50, Bo-Chen Chen ha scritto: From: Markus Schneider-Pargmann Similar to HDMI, DP uses audio infoframes as well which are structured very similar to the HDMI ones. This patch adds a helper function to pack the HDMI audio infoframe for DP, called hdmi_audio_infoframe_pack_for_dp(). hdmi_audio_infoframe_pack_only() is split into two parts. One of them packs the payload only and can be used for HDMI and DP. Also constify the frame parameter in hdmi_audio_infoframe_check() as it is passed to hdmi_audio_infoframe_check_only() which expects a const. Signed-off-by: Markus Schneider-Pargmann Signed-off-by: Guillaume Ranquet Signed-off-by: Bo-Chen Chen Reviewed-by: AngeloGioacchino Del Regno