[PATCH v4a 30/38] timers: dma-buf: Use timer_shutdown_sync() for on stack timers
From: "Steven Rostedt (Google)" Before a timer is released, timer_shutdown_sync() must be called. Link: https://lore.kernel.org/all/20221104054053.431922...@goodmis.org/ Cc: Sumit Semwal Cc: "Christian König" Cc: linux-me...@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Cc: linaro-mm-...@lists.linaro.org Signed-off-by: Steven Rostedt (Google) --- drivers/dma-buf/st-dma-fence.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma-buf/st-dma-fence.c b/drivers/dma-buf/st-dma-fence.c index fb6e0a6ae2c9..5d3e7b503501 100644 --- a/drivers/dma-buf/st-dma-fence.c +++ b/drivers/dma-buf/st-dma-fence.c @@ -412,7 +412,7 @@ static int test_wait_timeout(void *arg) err = 0; err_free: - del_timer_sync(&wt.timer); + timer_shutdown_sync(&wt.timer); destroy_timer_on_stack(&wt.timer); dma_fence_signal(wt.f); dma_fence_put(wt.f); -- 2.35.1
[PATCH v4a 31/38] timers: drm: Use timer_shutdown_sync() for on stack timers
From: "Steven Rostedt (Google)" Before a timer is released, timer_shutdown_sync() must be called. Link: https://lore.kernel.org/all/20221104054053.431922...@goodmis.org/ Cc: "Noralf Trønnes" Cc: David Airlie Cc: Daniel Vetter Cc: Jani Nikula Cc: Joonas Lahtinen Cc: Rodrigo Vivi Cc: Tvrtko Ursulin Cc: dri-devel@lists.freedesktop.org Cc: intel-...@lists.freedesktop.org Signed-off-by: Steven Rostedt (Google) --- drivers/gpu/drm/gud/gud_pipe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/gud/gud_pipe.c b/drivers/gpu/drm/gud/gud_pipe.c index 7c6dc2bcd14a..08429bdd57cf 100644 --- a/drivers/gpu/drm/gud/gud_pipe.c +++ b/drivers/gpu/drm/gud/gud_pipe.c @@ -272,7 +272,7 @@ static int gud_usb_bulk(struct gud_device *gdrm, size_t len) usb_sg_wait(&ctx.sgr); - if (!del_timer_sync(&ctx.timer)) + if (!timer_shutdown_sync(&ctx.timer)) ret = -ETIMEDOUT; else if (ctx.sgr.status < 0) ret = ctx.sgr.status; -- 2.35.1
[PATCH v4a 00/38] timers: Use timer_shutdown*() before freeing timers
Back in April, I posted an RFC patch set to help mitigate a common issue where a timer gets armed just before it is freed, and when the timer goes off, it crashes in the timer code without any evidence of who the culprit was. I got side tracked and never finished up on that patch set. Since this type of crash is still our #1 crash we are seeing in the field, it has become a priority again to finish it. The last version of that patch set is here: https://lore.kernel.org/all/20221104054053.431922...@goodmis.org/ I'm calling this version 4a as it only has obvious changes were the timer that is being shutdown is in the same function where it will be freed or released, as this series should be "safe" for adding. I'll be calling the other patches 4b for the next merge window. Patch 1 fixes an issue with sunrpc/xprt where it incorrectly uses del_singleshot_timer_sync() for something that is not a oneshot timer. As this will be converted to shutdown, this needs to be fixed first. Patches 2-4 changes existing timer_shutdown() functions used locally in ARM and some drivers to better namespace names. Patch 5 implements the new timer_shutdown() and timer_shutdown_sync() functions that disable re-arming the timer after they are called. Patches 6-28 change all the locations where there's a kfree(), kfree_rcu(), kmem_cache_free() and one call_rcu() call where the RCU function frees the timer (the workqueue patch) in the same function as the del_timer{,_sync}() is called on that timer, and there's no extra exit path between the del_timer and freeing of the timer. Patches 29-32 add timer_shutdown*() on on-stack timers that are about to be released at the end of the function. Patches 33-37 add timer_shutdown*() on module timers in the module exit code. Patch 38 simply converts an open coded "shutdown" code into timer_shutdown(), as a way timer_shutdown() disables the timer is by setting that timer function to NULL. Linus, I sorted the patches this way to let you see which you would think is safe to go into this -rc. I honestly believe that they are all safe, but that's just my own opinion. This series is here: git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git timers-start Head SHA1: f58b516a65bac76f1bfa00126856d6c6c3d24a40 Steven Rostedt (Google) (38): SUNRPC/xprt: Use del_timer_sync() instead of del_singleshot_timer_sync() ARM: spear: Do not use timer namespace for timer_shutdown() function clocksource/drivers/arm_arch_timer: Do not use timer namespace for timer_shutdown() function clocksource/drivers/sp804: Do not use timer namespace for timer_shutdown() function timers: Add timer_shutdown_sync() and timer_shutdown() to be called before freeing timers timers: sh: Use timer_shutdown_sync() before freeing timer timers: block: Use timer_shutdown_sync() before freeing timer timers: ACPI: Use timer_shutdown_sync() before freeing timer timers: atm: Use timer_shutdown_sync() before freeing timer timers: Bluetooth: Use timer_shutdown_sync() before freeing timer timers: drm: Use timer_shutdown_sync() before freeing timer timers: HID: Use timer_shutdown_sync() before freeing timer timers: Input: Use timer_shutdown_sync() before freeing timer timers: mISDN: Use timer_shutdown_sync() before freeing timer timers: leds: Use timer_shutdown_sync() before freeing timer timers: media: Use timer_shutdown_sync() before freeing timer timers: net: Use timer_shutdown_sync() before freeing timer timers: usb: Use timer_shutdown_sync() before freeing timer timers: nfc: pn533: Use timer_shutdown_sync() before freeing timer timers: pcmcia: Use timer_shutdown_sync() before freeing timer timers: scsi: Use timer_shutdown_sync() and timer_shutdown() before freeing timer timers: tty: Use timer_shutdown_sync() before freeing timer timers: ext4: Use timer_shutdown_sync() before freeing timer timers: fs/nilfs2: Use timer_shutdown_sync() before freeing timer timers: ALSA: Use timer_shutdown_sync() before freeing timer timers: jbd2: Use timer_shutdown() before freeing timer timers: sched/psi: Use timer_shutdown_sync() before freeing timer timers: workqueue: Use timer_shutdown_sync() before freeing timer random: use timer_shutdown_sync() for on stack timers timers: dma-buf: Use timer_shutdown_sync() for on stack timers timers: drm: Use timer_shutdown_sync() for on stack timers timers: media: Use timer_shutdown_sync() for on stack timers timers: s390/cmm: Use timer_shutdown_sync() before a module is released timers: atm: Use timer_shutdown_sync() before a module is released timers: hangcheck: Use timer_shutdown_sync() before a module is released timers: ipmi: Use timer_shutdown_sync() before a module is released timers: Input: Use timer_shutdown_sync() before a module is released timers: PM:
[PATCH v4a 11/38] timers: drm: Use timer_shutdown_sync() before freeing timer
From: "Steven Rostedt (Google)" Before a timer is freed, timer_shutdown_sync() must be called. Link: https://lore.kernel.org/all/20221104054053.431922...@goodmis.org/ Cc: "Noralf Trønnes" Cc: David Airlie Cc: Daniel Vetter Cc: Jani Nikula Cc: Joonas Lahtinen Cc: Rodrigo Vivi Cc: Tvrtko Ursulin Cc: dri-devel@lists.freedesktop.org Cc: intel-...@lists.freedesktop.org Signed-off-by: Steven Rostedt (Google) --- drivers/gpu/drm/i915/i915_sw_fence.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_sw_fence.c b/drivers/gpu/drm/i915/i915_sw_fence.c index 6fc0d1b89690..bfaa9a67dc35 100644 --- a/drivers/gpu/drm/i915/i915_sw_fence.c +++ b/drivers/gpu/drm/i915/i915_sw_fence.c @@ -465,7 +465,7 @@ static void irq_i915_sw_fence_work(struct irq_work *wrk) struct i915_sw_dma_fence_cb_timer *cb = container_of(wrk, typeof(*cb), work); - del_timer_sync(&cb->timer); + timer_shutdown_sync(&cb->timer); dma_fence_put(cb->dma); kfree_rcu(cb, rcu); -- 2.35.1
Re: [PATCH v2 1/2] drm/i915/guc: Properly initialise kernel contexts
On Wed, Nov 02, 2022 at 12:21:08PM -0700, john.c.harri...@intel.com wrote: From: John Harrison If a context has already been registered prior to first submission then context init code was not being called. The noticeable effect of that was the scheduling priority was left at zero (meaning super high priority) instead of being set to normal. This would occur with kernel contexts at start of day as they are manually pinned up front rather than on first submission. So add a call to initialise those when they are pinned. Signed-off-by: John Harrison Reviewed-by: Lucas De Marchi Lucas De Marchi --- drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 3 +++ 1 file changed, 3 insertions(+) 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 4ccb29f9ac55c..941613be3b9dd 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -4111,6 +4111,9 @@ static inline void guc_kernel_context_pin(struct intel_guc *guc, if (context_guc_id_invalid(ce)) pin_guc_id(guc, ce); + if (!test_bit(CONTEXT_GUC_INIT, &ce->flags)) + guc_context_init(ce); + try_context_registration(ce, true); } -- 2.37.3
Re: [Intel-gfx] [PATCH 1/2] drm/i915/gt: Add GT oriented dmesg output
On 11/4/2022 10:25 AM, john.c.harri...@intel.com wrote: From: John Harrison When trying to analyse bug reports from CI, customers, etc. it can be difficult to work out exactly what is happening on which GT in a multi-GT system. So add GT oriented debug/error message wrappers. If used instead of the drm_ equivalents, you get the same output but with a GT# prefix on it. Signed-off-by: John Harrison The only downside to this is that we'll print "GT0: " even on single-GT devices. We could introduce a gt->info.name and print that, so we could have it different per-platform, but IMO it's not worth the effort. Reviewed-by: Daniele Ceraolo Spurio I think it might be worth getting an ack from one of the maintainers to make sure we're all aligned on transitioning to these new logging macro for gt code. Daniele --- drivers/gpu/drm/i915/gt/intel_gt.h | 15 +++ 1 file changed, 15 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/intel_gt.h b/drivers/gpu/drm/i915/gt/intel_gt.h index e0365d5562484..1e016fb0117a4 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.h +++ b/drivers/gpu/drm/i915/gt/intel_gt.h @@ -13,6 +13,21 @@ struct drm_i915_private; struct drm_printer; +#define GT_ERR(_gt, _fmt, ...) \ + drm_err(&(_gt)->i915->drm, "GT%u: " _fmt, (_gt)->info.id, ##__VA_ARGS__) + +#define GT_WARN(_gt, _fmt, ...) \ + drm_warn(&(_gt)->i915->drm, "GT%u: " _fmt, (_gt)->info.id, ##__VA_ARGS__) + +#define GT_NOTICE(_gt, _fmt, ...) \ + drm_notice(&(_gt)->i915->drm, "GT%u: " _fmt, (_gt)->info.id, ##__VA_ARGS__) + +#define GT_INFO(_gt, _fmt, ...) \ + drm_info(&(_gt)->i915->drm, "GT%u: " _fmt, (_gt)->info.id, ##__VA_ARGS__) + +#define GT_DBG(_gt, _fmt, ...) \ + drm_dbg(&(_gt)->i915->drm, "GT%u: " _fmt, (_gt)->info.id, ##__VA_ARGS__) + #define GT_TRACE(gt, fmt, ...) do { \ const struct intel_gt *gt__ __maybe_unused = (gt); \ GEM_TRACE("%s " fmt, dev_name(gt__->i915->drm.dev), \
[PATCH 2/2] drm/display/dp_mst: Fix drm_dp_mst_add_affected_dsc_crtcs() return code
Looks like that we're accidentally dropping a pretty important return code here. For some reason, we just return -EINVAL if we fail to get the MST topology state. This is wrong: error codes are important and should never be squashed without being handled, which here seems to have the potential to cause a deadlock. Signed-off-by: Lyude Paul Fixes: 8ec046716ca8 ("drm/dp_mst: Add helper to trigger modeset on affected DSC MST CRTCs") Cc: # v5.6+ --- drivers/gpu/drm/display/drm_dp_mst_topology.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c index ecd22c038c8c0..51a46689cda70 100644 --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c @@ -5186,7 +5186,7 @@ int drm_dp_mst_add_affected_dsc_crtcs(struct drm_atomic_state *state, struct drm mst_state = drm_atomic_get_mst_topology_state(state, mgr); if (IS_ERR(mst_state)) - return -EINVAL; + return PTR_ERR(mst_state); list_for_each_entry(pos, &mst_state->payloads, next) { -- 2.37.3
[PATCH 1/2] drm/amdgpu/mst: Stop ignoring error codes and deadlocking
It appears that amdgpu makes the mistake of completely ignoring the return values from the DP MST helpers, and instead just returns a simple true/false. In this case, it seems to have come back to bite us because as a result of simply returning false from compute_mst_dsc_configs_for_state(), amdgpu had no way of telling when a deadlock happened from these helpers. This could definitely result in some kernel splats. Signed-off-by: Lyude Paul Fixes: 8c20a1ed9b4f ("drm/amd/display: MST DSC compute fair share") Cc: Harry Wentland Cc: # v5.6+ --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 18 +-- .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 107 ++ .../display/amdgpu_dm/amdgpu_dm_mst_types.h | 12 +- 3 files changed, 73 insertions(+), 64 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 0db2a88cd4d7b..6f76b2c84cdb5 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -6462,7 +6462,7 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state, struct drm_connector_state *new_con_state; struct amdgpu_dm_connector *aconnector; struct dm_connector_state *dm_conn_state; - int i, j; + int i, j, ret; int vcpi, pbn_div, pbn, slot_num = 0; for_each_new_connector_in_state(state, connector, new_con_state, i) { @@ -6509,8 +6509,11 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state, dm_conn_state->pbn = pbn; dm_conn_state->vcpi_slots = slot_num; - drm_dp_mst_atomic_enable_dsc(state, aconnector->port, dm_conn_state->pbn, -false); + ret = drm_dp_mst_atomic_enable_dsc(state, aconnector->port, + dm_conn_state->pbn, false); + if (ret != 0) + return ret; + continue; } @@ -9523,10 +9526,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, #if defined(CONFIG_DRM_AMD_DC_DCN) if (dc_resource_is_dsc_encoding_supported(dc)) { - if (!pre_validate_dsc(state, &dm_state, vars)) { - ret = -EINVAL; + ret = pre_validate_dsc(state, &dm_state, vars); + if (ret != 0) goto fail; - } } #endif @@ -9621,9 +9623,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, } #if defined(CONFIG_DRM_AMD_DC_DCN) - if (!compute_mst_dsc_configs_for_state(state, dm_state->context, vars)) { + ret = compute_mst_dsc_configs_for_state(state, dm_state->context, vars); + if (ret) { DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state() failed\n"); - ret = -EINVAL; goto fail; } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 6ff96b4bdda5c..30bc2e5058b70 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -864,25 +864,25 @@ static bool try_disable_dsc(struct drm_atomic_state *state, return true; } -static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, -struct dc_state *dc_state, -struct dc_link *dc_link, -struct dsc_mst_fairness_vars *vars, -struct drm_dp_mst_topology_mgr *mgr, -int *link_vars_start_index) +static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, + struct dc_state *dc_state, + struct dc_link *dc_link, + struct dsc_mst_fairness_vars *vars, + struct drm_dp_mst_topology_mgr *mgr, + int *link_vars_start_index) { struct dc_stream_state *stream; struct dsc_mst_fairness_params params[MAX_PIPES]; struct amdgpu_dm_connector *aconnector; struct drm_dp_mst_topology_state *mst_state = drm_atomic_get_mst_topology_state(state, mgr); int count = 0; - int i, k; + int i, k, ret; bool debugfs_overwrite = false; memset(params, 0, sizeof(params)); if (IS_ERR(mst_state)) - return false; + return PTR_ERR(mst_state); mst_state->pbn_div =
Re: [RFC][PATCH v3 00/33] timers: Use timer_shutdown*() before freeing timers
On Fri, Nov 04, 2022 at 01:40:53AM -0400, Steven Rostedt wrote: > > Back in April, I posted an RFC patch set to help mitigate a common issue > where a timer gets armed just before it is freed, and when the timer > goes off, it crashes in the timer code without any evidence of who the > culprit was. I got side tracked and never finished up on that patch set. > Since this type of crash is still our #1 crash we are seeing in the field, > it has become a priority again to finish it. > After applying the patches attached below, everything compiles for me, and there are no crashes. There are still various warnings, most in networking. I know I need to apply some patch(es) to fix the networking warnings, but I didn't entirely understand what exactly to apply, so I didn't try. Complete logs are at https://kerneltests.org/builders, on the bottom half of the page (qemu tests, in the 'testing' column). Guenter --- Warnings: ODEBUG: free active (active state 0) object type: timer_list hint: tcp_write_timer+0x0/0x1d0 from tcp_close -> __sk_destruct -> tcp_write_timer ODEBUG: free active (active state 0) object type: timer_list hint: tcp_keepalive_timer+0x0/0x4c0 from tcp_close -> __sk_destruct -> tcp_keepalive_timer -> __del_timer_sync ODEBUG: free active (active state 0) object type: timer_list hint: blk_rq_timed_out_timer+0x0/0x40 blk_free_queue_rcu -> blk_free_queue_rcu -> blk_rq_timed_out_timer --- Changes applied on top of patch set to fix build errors: diff --git a/arch/arm/mach-spear/time.c b/arch/arm/mach-spear/time.c index e979e2197f8e..5371c824786d 100644 --- a/arch/arm/mach-spear/time.c +++ b/arch/arm/mach-spear/time.c @@ -90,7 +90,7 @@ static void __init spear_clocksource_init(void) 200, 16, clocksource_mmio_readw_up); } -static inline void timer_shutdown(struct clock_event_device *evt) +static inline void spear_timer_shutdown(struct clock_event_device *evt) { u16 val = readw(gpt_base + CR(CLKEVT)); @@ -101,7 +101,7 @@ static inline void timer_shutdown(struct clock_event_device *evt) static int spear_shutdown(struct clock_event_device *evt) { - timer_shutdown(evt); + spear_timer_shutdown(evt); return 0; } @@ -111,7 +111,7 @@ static int spear_set_oneshot(struct clock_event_device *evt) u16 val; /* stop the timer */ - timer_shutdown(evt); + spear_timer_shutdown(evt); val = readw(gpt_base + CR(CLKEVT)); val |= CTRL_ONE_SHOT; @@ -126,7 +126,7 @@ static int spear_set_periodic(struct clock_event_device *evt) u16 val; /* stop the timer */ - timer_shutdown(evt); + spear_timer_shutdown(evt); period = clk_get_rate(gpt_clk) / HZ; period >>= CTRL_PRESCALER16; diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index a7ff77550e17..9c3420a0d19d 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -687,8 +687,8 @@ static irqreturn_t arch_timer_handler_virt_mem(int irq, void *dev_id) return timer_handler(ARCH_TIMER_MEM_VIRT_ACCESS, evt); } -static __always_inline int timer_shutdown(const int access, - struct clock_event_device *clk) +static __always_inline int arch_timer_shutdown(const int access, + struct clock_event_device *clk) { unsigned long ctrl; @@ -701,22 +701,22 @@ static __always_inline int timer_shutdown(const int access, static int arch_timer_shutdown_virt(struct clock_event_device *clk) { - return timer_shutdown(ARCH_TIMER_VIRT_ACCESS, clk); + return arch_timer_shutdown(ARCH_TIMER_VIRT_ACCESS, clk); } static int arch_timer_shutdown_phys(struct clock_event_device *clk) { - return timer_shutdown(ARCH_TIMER_PHYS_ACCESS, clk); + return arch_timer_shutdown(ARCH_TIMER_PHYS_ACCESS, clk); } static int arch_timer_shutdown_virt_mem(struct clock_event_device *clk) { - return timer_shutdown(ARCH_TIMER_MEM_VIRT_ACCESS, clk); + return arch_timer_shutdown(ARCH_TIMER_MEM_VIRT_ACCESS, clk); } static int arch_timer_shutdown_phys_mem(struct clock_event_device *clk) { - return timer_shutdown(ARCH_TIMER_MEM_PHYS_ACCESS, clk); + return arch_timer_shutdown(ARCH_TIMER_MEM_PHYS_ACCESS, clk); } static __always_inline void set_next_event(const int access, unsigned long evt, diff --git a/drivers/clocksource/timer-sp804.c b/drivers/clocksource/timer-sp804.c index e6a87f4af2b5..a3c38e1343f0 100644 --- a/drivers/clocksource/timer-sp804.c +++ b/drivers/clocksource/timer-sp804.c @@ -155,14 +155,14 @@ static irqreturn_t sp804_timer_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static inline void timer_shutdown(struct clock_event_device *evt) +static inline void sp804_timer_shutdown(struct clock_event_device *evt) { writel(0, common_clkevt->ctrl); } static int sp
[PATCH v3] drm/nouveau: Add support to control backlight using bl_power for nva3.
From: antoniospg Summary: * Add support to turn on/off backlight when changing values in bl_power file. This is achieved by using function backlight_get_brightness() in nva3_set_intensity to get current brightness. Test plan: * Turn off: echo 1 > /sys/class/backlight/nv_backlight/bl_power * Turn on: echo 0 > /sys/class/backlight/nv_backlight/bl_power Signed-off-by: antoniospg --- drivers/gpu/drm/nouveau/nouveau_backlight.c | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c index a2141d3d9b1d..5c82f5189b79 100644 --- a/drivers/gpu/drm/nouveau/nouveau_backlight.c +++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c @@ -263,7 +263,11 @@ nva3_set_intensity(struct backlight_device *bd) u32 div, val; div = nvif_rd32(device, NV50_PDISP_SOR_PWM_DIV(or)); - val = (bd->props.brightness * div) / 100; + + val = backlight_get_brightness(bd); + if (val) + val = (val * div) / 100; + if (div) { nvif_wr32(device, NV50_PDISP_SOR_PWM_CTL(or), val | -- 2.25.1
[PATCH v3] drm/nouveau: Add support to control backlight using bl_power for nva3.
From: antoniospg Summary: * Add support to turn on/off backlight when changing values in bl_power file. This is achieved by using function backlight_get_brightness() in nva3_set_intensity to get current brightness. Test plan: * Turn off: echo 1 > /sys/class/backlight/nv_backlight/bl_power * Turn on: echo 0 > /sys/class/backlight/nv_backlight/bl_power Signed-off-by: antoniospg --- drivers/gpu/drm/nouveau/nouveau_backlight.c | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c index a2141d3d9b1d..5c82f5189b79 100644 --- a/drivers/gpu/drm/nouveau/nouveau_backlight.c +++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c @@ -263,7 +263,11 @@ nva3_set_intensity(struct backlight_device *bd) u32 div, val; div = nvif_rd32(device, NV50_PDISP_SOR_PWM_DIV(or)); - val = (bd->props.brightness * div) / 100; + + val = backlight_get_brightness(bd); + if (val) + val = (val * div) / 100; + if (div) { nvif_wr32(device, NV50_PDISP_SOR_PWM_CTL(or), val | -- 2.25.1
Re: [git pull] drm fixes for 6.1-rc4
The pull request you sent on Fri, 4 Nov 2022 13:21:02 +1000: > git://anongit.freedesktop.org/drm/drm tags/drm-fixes-2022-11-04-1 has been merged into torvalds/linux.git: https://git.kernel.org/torvalds/c/fde25beb382b7dd6f2eab8022ab017cbdfaa3ff6 Thank you! -- Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/prtracker.html
[pull] amdgpu, amdkfd, radeon, drm drm-next-6.2
Hi Dave, Daniel, New stuff for 6.2. The following changes since commit 9abf2313adc1ca1b6180c508c25f22f9395cc780: Linux 6.1-rc1 (2022-10-16 15:36:24 -0700) are available in the Git repository at: https://gitlab.freedesktop.org/agd5f/linux.git tags/amd-drm-next-6.2-2022-11-04 for you to fetch changes up to fcf00f8d29f2fc6bf00531a1447be28b99073cc3: drm/amdkfd: Remove skiping userptr buffer mapping when mmu notifier marks it as invalid (2022-11-04 16:05:54 -0400) amd-drm-next-6.2-2022-11-04: amdgpu: - Add TMZ support for GC 11.0.1 - More IP version check conversions - Mode2 reset fixes for sienna cichlid - SMU 13.x fixes - RAS enablement on MP 13.x - Replace kmap with kmap_local_page() - Misc Clang warning fixes - SR-IOV fixes for GC 11.x - PCI AER fix - DCN 3.2.x commit sequence rework - SDMA 4.x doorbell fix - Expose additional new GC 11.x firmware versions - Misc code cleanups - S0i3 fixes - More DC FPU cleanup - Add more DC kerneldoc - Misc spelling and grammer fixes - DCN 3.1.x fixes - Plane modifier fix - MCA RAS enablement - Secure display locking fix - RAS TA rework - RAS EEPROM fixes - Fail suspend if eviction fails - Drop AMD specific DSC workarounds in favor of drm EDID quirks - SR-IOV suspend/resume fixes - Enable DCN support for ARM - Enable secure display on DCN 2.1 amdkfd: - Cache size fixes for GC 10.3.x - kfd_dev struct cleanup - GC11.x CWSR trap handler fix - Userptr fixes - Warning fixes radeon: - Replace kmap with kmap_local_page() UAPI: - Expose additional new GC 11.x firmware versions via the existing INFO query drm: - Add some new EDID DSC quirks Alan Liu (3): drm/amd/display: Implement secure display on DCN21 drm/amd/display: Drop struct crc_region and reuse struct rect drm/amdgpu: Move the mutex_lock to protect the return status of securedisplay command buffer Alex Deucher (6): drm/amdgpu: convert vega20_ih.c to IP version checks drm/amdgpu: convert amdgpu_amdkfd_gpuvm.c to IP version checks drm/amdgpu: fix sdma doorbell init ordering on APUs drm/amdgpu/gfx9: set gfx.funcs in early init drm/amdgpu/gfx10: set gfx.funcs in early init drm/amdgpu/gfx11: set gfx.funcs in early init Alvin Lee (4): drm/amd/display: Don't return false if no stream drm/amd/display: Remove optimization for VRR updates drm/amd/display: Enable timing sync on DCN32 drm/amd/display: Don't enable ODM + MPO Anthony Koo (2): drm/amd/display: Document part of the DMUB cmd drm/amd/display: [FW Promotion] Release 0.0.141.0 Ao Zhong (3): drm/amd/display: move remaining FPU code to dml folder drm/amd/display: move remaining FPU code to dml folder drm/amd/display: add DCN support for ARM64 Aric Cyr (4): drm/amd/display: 3.2.208 drm/amd/display: Fix SDR visual confirm drm/amd/display: 3.2.209 drm/amd/display: 3.2.210 Arunpravin Paneer Selvam (1): drm/amdgpu: Fix for BO move issue Asher Song (1): drm/amdgpu: Revert "drm/amdgpu: getting fan speed pwm for vega10 properly" Bhawanpreet Lakha (1): drm/amd/display: Fix HDCP 1.X 1A-04 failing Candice Li (5): drm/amdgpu: Optimize RAS TA initialization and TA unload funcs drm/amdgpu: Optimize TA load/unload/invoke debugfs interfaces drm/amdgpu: Update ras eeprom support for smu v13_0_0 and v13_0_10 drm/amdgpu: Add EEPROM I2C address support for ip discovery drm/amdgpu: Enable GFX RAS feature for gfx v11_0_3 Charlene Liu (2): drm/amd/display: Update DML formula drm/amd/display: Fix null pointer issues found in emulation Chengming Gui (1): drm/amdgpu: fix pstate setting issue Danijel Slivka (1): drm/amdgpu: set vm_update_mode=0 as default for Sienna Cichlid in SRIOV case David Francis (1): drm/amd: Add IMU fw version to fw version queries Deming Wang (1): drm/amdkfd: use vma_lookup() instead of find_vma() Dillon Varone (4): drm/amd/display: Update latencies on DCN321 drm/amd/display: Set memclk levels to be at least 1 for dcn32 drm/amd/display: Reinit DPG when exiting dynamic ODM drm/amd/display: Check validation passed after applying pipe split changes Dmytro Laktyushkin (1): drm/amd/display: correctly populate dcn315 clock table Eric Bernstein (1): drm/amd/display: Include virtual signal to set k1 and k2 values Evan Quan (3): drm/amd/pm: fulfill SMU13.0.0 cstate control interface drm/amd/pm: fulfill SMU13.0.7 cstate control interface drm/amd/pm: disable cstate feature for gpu reset scenario Fabio M. De Francesco (2): drm/radeon: Replace kmap() with kmap_local_page() drm/amd/amdgpu: Replace kmap() with kmap_local_page() Fangzhi Zuo (3): drm/amd/display: Add UHBR135 and UHBR20 into debugfs drm/amd/display: Ignore Cable ID Featur
Re: [PATCH] drm/panfrost: Update io-pgtable API
On 11/4/22 23:37, Robin Murphy wrote: > On 2022-11-04 20:11, Dmitry Osipenko wrote: >> On 8/23/22 01:01, Robin Murphy wrote: >>> Convert to io-pgtable's bulk {map,unmap}_pages() APIs, to help the old >>> single-page interfaces eventually go away. Unmapping heap BOs still >>> wants to be done a page at a time, but everything else can get the full >>> benefit of the more efficient interface. >>> >>> Signed-off-by: Robin Murphy >>> --- >>> drivers/gpu/drm/panfrost/panfrost_mmu.c | 40 +++-- >>> 1 file changed, 25 insertions(+), 15 deletions(-) >>> >>> diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c >>> b/drivers/gpu/drm/panfrost/panfrost_mmu.c >>> index b285a8001b1d..e246d914e7f6 100644 >>> --- a/drivers/gpu/drm/panfrost/panfrost_mmu.c >>> +++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c >>> @@ -248,11 +248,15 @@ void panfrost_mmu_reset(struct panfrost_device >>> *pfdev) >>> mmu_write(pfdev, MMU_INT_MASK, ~0); >>> } >>> -static size_t get_pgsize(u64 addr, size_t size) >>> +static size_t get_pgsize(u64 addr, size_t size, size_t *count) >>> { >>> - if (addr & (SZ_2M - 1) || size < SZ_2M) >>> - return SZ_4K; >>> + size_t blk_offset = -addr % SZ_2M; >>> + if (blk_offset || size < SZ_2M) { >>> + *count = min_not_zero(blk_offset, size) / SZ_4K; >>> + return SZ_4K; >>> + } >>> + *count = size / SZ_2M; >>> return SZ_2M; >>> } >>> @@ -287,12 +291,16 @@ static int mmu_map_sg(struct panfrost_device >>> *pfdev, struct panfrost_mmu *mmu, >>> dev_dbg(pfdev->dev, "map: as=%d, iova=%llx, paddr=%lx, >>> len=%zx", mmu->as, iova, paddr, len); >>> while (len) { >>> - size_t pgsize = get_pgsize(iova | paddr, len); >>> + size_t pgcount, mapped = 0; >>> + size_t pgsize = get_pgsize(iova | paddr, len, &pgcount); >>> - ops->map(ops, iova, paddr, pgsize, prot, GFP_KERNEL); >>> - iova += pgsize; >>> - paddr += pgsize; >>> - len -= pgsize; >>> + ops->map_pages(ops, iova, paddr, pgsize, pgcount, prot, >>> + GFP_KERNEL, &mapped); >>> + /* Don't get stuck if things have gone wrong */ >>> + mapped = max(mapped, pgsize); >>> + iova += mapped; >>> + paddr += mapped; >>> + len -= mapped; >>> } >>> } >>> @@ -344,15 +352,17 @@ void panfrost_mmu_unmap(struct >>> panfrost_gem_mapping *mapping) >>> mapping->mmu->as, iova, len); >>> while (unmapped_len < len) { >>> - size_t unmapped_page; >>> - size_t pgsize = get_pgsize(iova, len - unmapped_len); >>> + size_t unmapped_page, pgcount; >>> + size_t pgsize = get_pgsize(iova, len - unmapped_len, &pgcount); >>> - if (ops->iova_to_phys(ops, iova)) { >>> - unmapped_page = ops->unmap(ops, iova, pgsize, NULL); >>> - WARN_ON(unmapped_page != pgsize); >>> + if (bo->is_heap) >>> + pgcount = 1; >>> + if (!bo->is_heap || ops->iova_to_phys(ops, iova)) { >>> + unmapped_page = ops->unmap_pages(ops, iova, pgsize, >>> pgcount, NULL); >>> + WARN_ON(unmapped_page != pgsize * pgcount); >> >> This patch causes this WARN_ON to trigger. It doesn't happen all the >> time, I see that the whole unmapped area is mapped. Initially, I thought >> that this happens because it tries to unmap a partially mapped range, >> but I checked that ops->iova_to_phys() returns address for all 4k chunks. >> >> For example the pgsize * pgcount = 0x800, while returned >> unmapped_page = 0x600. >> >> I don't see this problem with this patch reverted. This is using today's >> linux-next. Any ideas? > > What's the base IOVA in such a case? I'm wondering if the truncated size > lines up to any interesting boundary. Presumably you're not seeing any > additional warnings from io-pgtable itself? No warnings from io-pgtable. It succeeds for 0x3200 and fails for 0x3a00 using same size 0x800. It actually fails only for the 0x3a00 as far as I see from my logs. Perhaps it indeed has to do something with the boundary. -- Best regards, Dmitry
Re: [RFC][PATCH v3 00/33] timers: Use timer_shutdown*() before freeing timers
On Fri, Nov 04, 2022 at 04:38:34PM -0400, Steven Rostedt wrote: > On Fri, 4 Nov 2022 15:42:09 -0400 > Steven Rostedt wrote: > [ ... ] > > > drivers/clocksource/timer-fttmr010.c: fttmr010->timer_shutdown(evt); > > drivers/clocksource/timer-fttmr010.c: fttmr010->timer_shutdown(evt); > > drivers/clocksource/timer-fttmr010.c: fttmr010->timer_shutdown(evt); > > drivers/clocksource/timer-fttmr010.c: fttmr010->timer_shutdown = > > ast2600_timer_shutdown; > > drivers/clocksource/timer-fttmr010.c: fttmr010->timer_shutdown = > > fttmr010_timer_shutdown; > > drivers/clocksource/timer-fttmr010.c: fttmr010->clkevt.set_state_shutdown > > = fttmr010->timer_shutdown; > > drivers/clocksource/timer-fttmr010.c: fttmr010->clkevt.tick_resume = > > fttmr010->timer_shutdown; > > I won't touch structure fields though. > Agreed, same here. Guenter
Re: [RFC][PATCH v3 00/33] timers: Use timer_shutdown*() before freeing timers
On Fri, Nov 04, 2022 at 03:42:09PM -0400, Steven Rostedt wrote: > On Fri, 4 Nov 2022 12:22:32 -0700 > Guenter Roeck wrote: > > > Unfortunately the renaming caused some symbol conflicts. > > > > Global definition: timer_shutdown > > > > File Line > > 0 time.c93 static inline void timer_shutdown(struct > > clock_event_device *evt) > > 1 arm_arch_timer.c 690 static __always_inline int timer_shutdown(const int > > access, > > 2 timer-fttmr010.c 105 int (*timer_shutdown)(struct clock_event_device > > *evt); > > 3 timer-sp804.c158 static inline void timer_shutdown(struct > > clock_event_device *evt) > > 4 timer.h 239 static inline int timer_shutdown(struct timer_list > > *timer) > > $ git grep '\btimer_shutdown' > arch/arm/mach-spear/time.c:static inline void timer_shutdown(struct > clock_event_device *evt) > arch/arm/mach-spear/time.c: timer_shutdown(evt); > arch/arm/mach-spear/time.c: timer_shutdown(evt); > arch/arm/mach-spear/time.c: timer_shutdown(evt); > drivers/clocksource/arm_arch_timer.c:static __always_inline int > timer_shutdown(const int access, > drivers/clocksource/arm_arch_timer.c: return > timer_shutdown(ARCH_TIMER_VIRT_ACCESS, clk); > drivers/clocksource/arm_arch_timer.c: return > timer_shutdown(ARCH_TIMER_PHYS_ACCESS, clk); > drivers/clocksource/arm_arch_timer.c: return > timer_shutdown(ARCH_TIMER_MEM_VIRT_ACCESS, clk); > drivers/clocksource/arm_arch_timer.c: return > timer_shutdown(ARCH_TIMER_MEM_PHYS_ACCESS, clk); > drivers/clocksource/timer-fttmr010.c: int (*timer_shutdown)(struct > clock_event_device *evt); > drivers/clocksource/timer-fttmr010.c: fttmr010->timer_shutdown(evt); > drivers/clocksource/timer-fttmr010.c: fttmr010->timer_shutdown(evt); > drivers/clocksource/timer-fttmr010.c: fttmr010->timer_shutdown(evt); > drivers/clocksource/timer-fttmr010.c: fttmr010->timer_shutdown = > ast2600_timer_shutdown; > drivers/clocksource/timer-fttmr010.c: fttmr010->timer_shutdown = > fttmr010_timer_shutdown; > drivers/clocksource/timer-fttmr010.c: fttmr010->clkevt.set_state_shutdown = > fttmr010->timer_shutdown; > drivers/clocksource/timer-fttmr010.c: fttmr010->clkevt.tick_resume = > fttmr010->timer_shutdown; > drivers/clocksource/timer-sp804.c:static inline void timer_shutdown(struct > clock_event_device *evt) > drivers/clocksource/timer-sp804.c: timer_shutdown(evt); > drivers/clocksource/timer-sp804.c: timer_shutdown(evt); > > Honestly, I think these need to be renamed, as "timer_shutdown()" > should be specific to the timer code, and not individual timers. Yes, that is what I did locally. I am repeating my test now with that change made. Guenter
Re: Coverity: kfd_parse_subtype_cache(): Memory - corruptions
On 2022-11-04 15:41, coverity-bot wrote: Hello! This is an experimental semi-automated report about issues detected by Coverity from a scan of next-20221104 as part of the linux-next scan project: https://scan.coverity.com/projects/linux-next-weekly-scan You're getting this email because you were associated with the identified lines of code (noted below) that were touched by commits: Fri Dec 8 23:08:59 2017 -0500 3a87177eb141 ("drm/amdkfd: Add topology support for dGPUs") Coverity reported the following: *** CID 1527133: Memory - corruptions (OVERRUN) drivers/gpu/drm/amd/amdkfd/kfd_crat.c:1113 in kfd_parse_subtype_cache() 1107props->cache_size = cache->cache_size; 1108props->cacheline_size = cache->cache_line_size; 1109props->cachelines_per_tag = cache->lines_per_tag; 1110props->cache_assoc = cache->associativity; props->cache_latency = cache->cache_latency; 1112 vvv CID 1527133: Memory - corruptions (OVERRUN) vvv Overrunning array "cache->sibling_map" of 32 bytes by passing it to a function which accesses it at byte offset 63 using argument "64UL". [Note: The source code implementation of the function has been overridden by a builtin model.] 1113memcpy(props->sibling_map, cache->sibling_map, 1114sizeof(props->sibling_map)); 1115 1116/* set the sibling_map_size as 32 for CRAT from ACPI */ 1117props->sibling_map_size = CRAT_SIBLINGMAP_SIZE; 1118 If this is a false positive, please let us know so we can mark it as such, or teach the Coverity rules to be smarter. If not, please make sure fixes get into linux-next. :) For patches fixing this, please include these lines (but double-check the "Fixes" first): Reported-by: coverity-bot Addresses-Coverity-ID: 1527133 ("Memory - corruptions") Fixes: 3a87177eb141 ("drm/amdkfd: Add topology support for dGPUs") I'm not sure why this suddenly appeared after 5 years, but the read over-run looks legit: I think this was introduced by a more recent patch that was in fact meant to fix an array overrun on HW that is outgrowing the CRAT sibling map size: commit 0938fbeb6f53fc44bc9b19784dee28496e68ba0c Author: Ma Jun Date: Wed Nov 2 15:53:26 2022 +0800 drm/amdkfd: Fix the warning of array-index-out-of-bounds For some GPUs with more CUs, the original sibling_map[32] in struct crat_subtype_cache is not enough to save the cache information when create the VCRAT table, so skip filling the struct crat_subtype_cache info instead fill struct kfd_cache_properties directly to fix this problem. Signed-off-by: Ma Jun Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher I added Ma Jun to the email. Regards, Felix struct crat_subtype_cache { ... uint8_t sibling_map[CRAT_SIBLINGMAP_SIZE]; #define CRAT_SIBLINGMAP_SIZE32 struct kfd_cache_properties { ... uint8_t sibling_map[CACHE_SIBLINGMAP_SIZE]; #define CACHE_SIBLINGMAP_SIZE 64 Thanks for your attention!
Re: [RFC][PATCH v3 00/33] timers: Use timer_shutdown*() before freeing timers
On Fri, 4 Nov 2022 15:42:09 -0400 Steven Rostedt wrote: > $ git grep '\btimer_shutdown' > arch/arm/mach-spear/time.c:static inline void timer_shutdown(struct > clock_event_device *evt) > arch/arm/mach-spear/time.c: timer_shutdown(evt); > arch/arm/mach-spear/time.c: timer_shutdown(evt); > arch/arm/mach-spear/time.c: timer_shutdown(evt); > drivers/clocksource/arm_arch_timer.c:static __always_inline int > timer_shutdown(const int access, > drivers/clocksource/arm_arch_timer.c: return > timer_shutdown(ARCH_TIMER_VIRT_ACCESS, clk); > drivers/clocksource/arm_arch_timer.c: return > timer_shutdown(ARCH_TIMER_PHYS_ACCESS, clk); > drivers/clocksource/arm_arch_timer.c: return > timer_shutdown(ARCH_TIMER_MEM_VIRT_ACCESS, clk); > drivers/clocksource/arm_arch_timer.c: return > timer_shutdown(ARCH_TIMER_MEM_PHYS_ACCESS, clk); > drivers/clocksource/timer-fttmr010.c: int (*timer_shutdown)(struct > clock_event_device *evt); > drivers/clocksource/timer-fttmr010.c: fttmr010->timer_shutdown(evt); > drivers/clocksource/timer-fttmr010.c: fttmr010->timer_shutdown(evt); > drivers/clocksource/timer-fttmr010.c: fttmr010->timer_shutdown(evt); > drivers/clocksource/timer-fttmr010.c: fttmr010->timer_shutdown = > ast2600_timer_shutdown; > drivers/clocksource/timer-fttmr010.c: fttmr010->timer_shutdown = > fttmr010_timer_shutdown; > drivers/clocksource/timer-fttmr010.c: fttmr010->clkevt.set_state_shutdown = > fttmr010->timer_shutdown; > drivers/clocksource/timer-fttmr010.c: fttmr010->clkevt.tick_resume = > fttmr010->timer_shutdown; I won't touch structure fields though. -- Steve > drivers/clocksource/timer-sp804.c:static inline void timer_shutdown(struct > clock_event_device *evt) > drivers/clocksource/timer-sp804.c: timer_shutdown(evt); > drivers/clocksource/timer-sp804.c: timer_shutdown(evt);
Re: [PATCH] drm/panfrost: Update io-pgtable API
On 2022-11-04 20:11, Dmitry Osipenko wrote: On 8/23/22 01:01, Robin Murphy wrote: Convert to io-pgtable's bulk {map,unmap}_pages() APIs, to help the old single-page interfaces eventually go away. Unmapping heap BOs still wants to be done a page at a time, but everything else can get the full benefit of the more efficient interface. Signed-off-by: Robin Murphy --- drivers/gpu/drm/panfrost/panfrost_mmu.c | 40 +++-- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c index b285a8001b1d..e246d914e7f6 100644 --- a/drivers/gpu/drm/panfrost/panfrost_mmu.c +++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c @@ -248,11 +248,15 @@ void panfrost_mmu_reset(struct panfrost_device *pfdev) mmu_write(pfdev, MMU_INT_MASK, ~0); } -static size_t get_pgsize(u64 addr, size_t size) +static size_t get_pgsize(u64 addr, size_t size, size_t *count) { - if (addr & (SZ_2M - 1) || size < SZ_2M) - return SZ_4K; + size_t blk_offset = -addr % SZ_2M; + if (blk_offset || size < SZ_2M) { + *count = min_not_zero(blk_offset, size) / SZ_4K; + return SZ_4K; + } + *count = size / SZ_2M; return SZ_2M; } @@ -287,12 +291,16 @@ static int mmu_map_sg(struct panfrost_device *pfdev, struct panfrost_mmu *mmu, dev_dbg(pfdev->dev, "map: as=%d, iova=%llx, paddr=%lx, len=%zx", mmu->as, iova, paddr, len); while (len) { - size_t pgsize = get_pgsize(iova | paddr, len); + size_t pgcount, mapped = 0; + size_t pgsize = get_pgsize(iova | paddr, len, &pgcount); - ops->map(ops, iova, paddr, pgsize, prot, GFP_KERNEL); - iova += pgsize; - paddr += pgsize; - len -= pgsize; + ops->map_pages(ops, iova, paddr, pgsize, pgcount, prot, + GFP_KERNEL, &mapped); + /* Don't get stuck if things have gone wrong */ + mapped = max(mapped, pgsize); + iova += mapped; + paddr += mapped; + len -= mapped; } } @@ -344,15 +352,17 @@ void panfrost_mmu_unmap(struct panfrost_gem_mapping *mapping) mapping->mmu->as, iova, len); while (unmapped_len < len) { - size_t unmapped_page; - size_t pgsize = get_pgsize(iova, len - unmapped_len); + size_t unmapped_page, pgcount; + size_t pgsize = get_pgsize(iova, len - unmapped_len, &pgcount); - if (ops->iova_to_phys(ops, iova)) { - unmapped_page = ops->unmap(ops, iova, pgsize, NULL); - WARN_ON(unmapped_page != pgsize); + if (bo->is_heap) + pgcount = 1; + if (!bo->is_heap || ops->iova_to_phys(ops, iova)) { + unmapped_page = ops->unmap_pages(ops, iova, pgsize, pgcount, NULL); + WARN_ON(unmapped_page != pgsize * pgcount); This patch causes this WARN_ON to trigger. It doesn't happen all the time, I see that the whole unmapped area is mapped. Initially, I thought that this happens because it tries to unmap a partially mapped range, but I checked that ops->iova_to_phys() returns address for all 4k chunks. For example the pgsize * pgcount = 0x800, while returned unmapped_page = 0x600. I don't see this problem with this patch reverted. This is using today's linux-next. Any ideas? What's the base IOVA in such a case? I'm wondering if the truncated size lines up to any interesting boundary. Presumably you're not seeing any additional warnings from io-pgtable itself? Thanks, Robin.
Re: [PATCH] drm/panfrost: Update io-pgtable API
On 8/23/22 01:01, Robin Murphy wrote: > Convert to io-pgtable's bulk {map,unmap}_pages() APIs, to help the old > single-page interfaces eventually go away. Unmapping heap BOs still > wants to be done a page at a time, but everything else can get the full > benefit of the more efficient interface. > > Signed-off-by: Robin Murphy > --- > drivers/gpu/drm/panfrost/panfrost_mmu.c | 40 +++-- > 1 file changed, 25 insertions(+), 15 deletions(-) > > diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c > b/drivers/gpu/drm/panfrost/panfrost_mmu.c > index b285a8001b1d..e246d914e7f6 100644 > --- a/drivers/gpu/drm/panfrost/panfrost_mmu.c > +++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c > @@ -248,11 +248,15 @@ void panfrost_mmu_reset(struct panfrost_device *pfdev) > mmu_write(pfdev, MMU_INT_MASK, ~0); > } > > -static size_t get_pgsize(u64 addr, size_t size) > +static size_t get_pgsize(u64 addr, size_t size, size_t *count) > { > - if (addr & (SZ_2M - 1) || size < SZ_2M) > - return SZ_4K; > + size_t blk_offset = -addr % SZ_2M; > > + if (blk_offset || size < SZ_2M) { > + *count = min_not_zero(blk_offset, size) / SZ_4K; > + return SZ_4K; > + } > + *count = size / SZ_2M; > return SZ_2M; > } > > @@ -287,12 +291,16 @@ static int mmu_map_sg(struct panfrost_device *pfdev, > struct panfrost_mmu *mmu, > dev_dbg(pfdev->dev, "map: as=%d, iova=%llx, paddr=%lx, > len=%zx", mmu->as, iova, paddr, len); > > while (len) { > - size_t pgsize = get_pgsize(iova | paddr, len); > + size_t pgcount, mapped = 0; > + size_t pgsize = get_pgsize(iova | paddr, len, &pgcount); > > - ops->map(ops, iova, paddr, pgsize, prot, GFP_KERNEL); > - iova += pgsize; > - paddr += pgsize; > - len -= pgsize; > + ops->map_pages(ops, iova, paddr, pgsize, pgcount, prot, > +GFP_KERNEL, &mapped); > + /* Don't get stuck if things have gone wrong */ > + mapped = max(mapped, pgsize); > + iova += mapped; > + paddr += mapped; > + len -= mapped; > } > } > > @@ -344,15 +352,17 @@ void panfrost_mmu_unmap(struct panfrost_gem_mapping > *mapping) > mapping->mmu->as, iova, len); > > while (unmapped_len < len) { > - size_t unmapped_page; > - size_t pgsize = get_pgsize(iova, len - unmapped_len); > + size_t unmapped_page, pgcount; > + size_t pgsize = get_pgsize(iova, len - unmapped_len, &pgcount); > > - if (ops->iova_to_phys(ops, iova)) { > - unmapped_page = ops->unmap(ops, iova, pgsize, NULL); > - WARN_ON(unmapped_page != pgsize); > + if (bo->is_heap) > + pgcount = 1; > + if (!bo->is_heap || ops->iova_to_phys(ops, iova)) { > + unmapped_page = ops->unmap_pages(ops, iova, pgsize, > pgcount, NULL); > + WARN_ON(unmapped_page != pgsize * pgcount); This patch causes this WARN_ON to trigger. It doesn't happen all the time, I see that the whole unmapped area is mapped. Initially, I thought that this happens because it tries to unmap a partially mapped range, but I checked that ops->iova_to_phys() returns address for all 4k chunks. For example the pgsize * pgcount = 0x800, while returned unmapped_page = 0x600. I don't see this problem with this patch reverted. This is using today's linux-next. Any ideas? -- Best regards, Dmitry
Re: [PATCH 07/10] vfio-iommufd: Support iommufd for physical VFIO devices
On Tue, Nov 01, 2022 at 08:21:20AM +, Tian, Kevin wrote: > > From: Jason Gunthorpe > > Sent: Wednesday, October 26, 2022 2:51 AM > > > > +int vfio_iommufd_bind(struct vfio_device *vdev, struct iommufd_ctx *ictx) > > +{ > > + u32 ioas_id; > > + u32 device_id; > > + int ret; > > + > > + lockdep_assert_held(&vdev->dev_set->lock); > > + > > + /* > > +* If the driver doesn't provide this op then it means the device does > > +* not do DMA at all. So nothing to do. > > +*/ > > + if (!vdev->ops->bind_iommufd) > > + return 0; > > Nothing to do or return -EOPNOTSUPP? As in the other email, nothing to do, driver is "bound" but doesn't actually need iommufd at all. > > + ret = vdev->ops->bind_iommufd(vdev, ictx, &device_id); > > + if (ret) > > + return ret; > > + > > + if (vdev->ops->attach_ioas) { > > __vfio_register_dev() already verifies that all three callbacks must > co-exist. Then no need to check it again here and later. Ok > > +void vfio_iommufd_unbind(struct vfio_device *vdev) > > +{ > > + lockdep_assert_held(&vdev->dev_set->lock); > > + > > + if (!vdev->iommufd_device) > > + return; > > there is no iommufd_device in the emulated path... Yes, this if should just be deleted Thanks, Jason
Re: [RFC][PATCH v3 00/33] timers: Use timer_shutdown*() before freeing timers
On Fri, Nov 4, 2022 at 12:42 PM Steven Rostedt wrote: > > Linus, should I also add any patches that has already been acked by the > respective maintainer? No, I'd prefer to keep only the ones that are 100% unambiguously not changing any semantics. Linus
Re: [PATCH 05/10] vfio: Use IOMMU_CAP_ENFORCE_CACHE_COHERENCY for vfio_file_enforced_coherent()
On Thu, Nov 03, 2022 at 04:38:16AM +, Tian, Kevin wrote: > > From: Jason Gunthorpe > > Sent: Tuesday, November 1, 2022 8:26 PM > > And this: > > > > /* > > * If the device does not have > > IOMMU_CAP_ENFORCE_CACHE_COHERENCY then > > * any domain later attached to it will also not support it. If the cap > > * is set then the iommu_domain eventually attached to the > > device/group > > * must must use a domain with enforce_cache_coherency(). > > */ > > duplicated 'must' Done Jason
Re: [RFC][PATCH v3 00/33] timers: Use timer_shutdown*() before freeing timers
On Fri, 4 Nov 2022 12:22:32 -0700 Guenter Roeck wrote: > Unfortunately the renaming caused some symbol conflicts. > > Global definition: timer_shutdown > > File Line > 0 time.c93 static inline void timer_shutdown(struct > clock_event_device *evt) > 1 arm_arch_timer.c 690 static __always_inline int timer_shutdown(const int > access, > 2 timer-fttmr010.c 105 int (*timer_shutdown)(struct clock_event_device *evt); > 3 timer-sp804.c158 static inline void timer_shutdown(struct > clock_event_device *evt) > 4 timer.h 239 static inline int timer_shutdown(struct timer_list > *timer) $ git grep '\btimer_shutdown' arch/arm/mach-spear/time.c:static inline void timer_shutdown(struct clock_event_device *evt) arch/arm/mach-spear/time.c: timer_shutdown(evt); arch/arm/mach-spear/time.c: timer_shutdown(evt); arch/arm/mach-spear/time.c: timer_shutdown(evt); drivers/clocksource/arm_arch_timer.c:static __always_inline int timer_shutdown(const int access, drivers/clocksource/arm_arch_timer.c: return timer_shutdown(ARCH_TIMER_VIRT_ACCESS, clk); drivers/clocksource/arm_arch_timer.c: return timer_shutdown(ARCH_TIMER_PHYS_ACCESS, clk); drivers/clocksource/arm_arch_timer.c: return timer_shutdown(ARCH_TIMER_MEM_VIRT_ACCESS, clk); drivers/clocksource/arm_arch_timer.c: return timer_shutdown(ARCH_TIMER_MEM_PHYS_ACCESS, clk); drivers/clocksource/timer-fttmr010.c: int (*timer_shutdown)(struct clock_event_device *evt); drivers/clocksource/timer-fttmr010.c: fttmr010->timer_shutdown(evt); drivers/clocksource/timer-fttmr010.c: fttmr010->timer_shutdown(evt); drivers/clocksource/timer-fttmr010.c: fttmr010->timer_shutdown(evt); drivers/clocksource/timer-fttmr010.c: fttmr010->timer_shutdown = ast2600_timer_shutdown; drivers/clocksource/timer-fttmr010.c: fttmr010->timer_shutdown = fttmr010_timer_shutdown; drivers/clocksource/timer-fttmr010.c: fttmr010->clkevt.set_state_shutdown = fttmr010->timer_shutdown; drivers/clocksource/timer-fttmr010.c: fttmr010->clkevt.tick_resume = fttmr010->timer_shutdown; drivers/clocksource/timer-sp804.c:static inline void timer_shutdown(struct clock_event_device *evt) drivers/clocksource/timer-sp804.c: timer_shutdown(evt); drivers/clocksource/timer-sp804.c: timer_shutdown(evt); Honestly, I think these need to be renamed, as "timer_shutdown()" should be specific to the timer code, and not individual timers. I'll start making a patch set that starts by renaming these timers, then adds the timer_shutdown() API, and finished with the trivial updates, and that will be a real "PATCH" (non RFC). Linus, should I also add any patches that has already been acked by the respective maintainer? -- Steve
Coverity: kfd_parse_subtype_cache(): Memory - corruptions
Hello! This is an experimental semi-automated report about issues detected by Coverity from a scan of next-20221104 as part of the linux-next scan project: https://scan.coverity.com/projects/linux-next-weekly-scan You're getting this email because you were associated with the identified lines of code (noted below) that were touched by commits: Fri Dec 8 23:08:59 2017 -0500 3a87177eb141 ("drm/amdkfd: Add topology support for dGPUs") Coverity reported the following: *** CID 1527133: Memory - corruptions (OVERRUN) drivers/gpu/drm/amd/amdkfd/kfd_crat.c:1113 in kfd_parse_subtype_cache() 1107props->cache_size = cache->cache_size; 1108props->cacheline_size = cache->cache_line_size; 1109props->cachelines_per_tag = cache->lines_per_tag; 1110props->cache_assoc = cache->associativity; props->cache_latency = cache->cache_latency; 1112 vvv CID 1527133: Memory - corruptions (OVERRUN) vvv Overrunning array "cache->sibling_map" of 32 bytes by passing it to a function which accesses it at byte offset 63 using argument "64UL". [Note: The source code implementation of the function has been overridden by a builtin model.] 1113memcpy(props->sibling_map, cache->sibling_map, 1114sizeof(props->sibling_map)); 1115 1116/* set the sibling_map_size as 32 for CRAT from ACPI */ 1117props->sibling_map_size = CRAT_SIBLINGMAP_SIZE; 1118 If this is a false positive, please let us know so we can mark it as such, or teach the Coverity rules to be smarter. If not, please make sure fixes get into linux-next. :) For patches fixing this, please include these lines (but double-check the "Fixes" first): Reported-by: coverity-bot Addresses-Coverity-ID: 1527133 ("Memory - corruptions") Fixes: 3a87177eb141 ("drm/amdkfd: Add topology support for dGPUs") I'm not sure why this suddenly appeared after 5 years, but the read over-run looks legit: struct crat_subtype_cache { ... uint8_t sibling_map[CRAT_SIBLINGMAP_SIZE]; #define CRAT_SIBLINGMAP_SIZE32 struct kfd_cache_properties { ... uint8_t sibling_map[CACHE_SIBLINGMAP_SIZE]; #define CACHE_SIBLINGMAP_SIZE 64 Thanks for your attention! -- Coverity-bot
Re: [RFC][PATCH v3 00/33] timers: Use timer_shutdown*() before freeing timers
On Fri, Nov 04, 2022 at 01:40:53AM -0400, Steven Rostedt wrote: > > Back in April, I posted an RFC patch set to help mitigate a common issue > where a timer gets armed just before it is freed, and when the timer > goes off, it crashes in the timer code without any evidence of who the > culprit was. I got side tracked and never finished up on that patch set. > Since this type of crash is still our #1 crash we are seeing in the field, > it has become a priority again to finish it. > > This is v3 of that patch set. Thomas Gleixner posted an untested version > that makes timer->function NULL as the flag that it is shutdown. I took that > code, tested it (fixed it up), added more comments, and changed the > name to timer_shutdown_sync(). I also converted it to use WARN_ON_ONCE() > instead of just WARN_ON() as Linus asked for. > Unfortunately the renaming caused some symbol conflicts. Global definition: timer_shutdown File Line 0 time.c93 static inline void timer_shutdown(struct clock_event_device *evt) 1 arm_arch_timer.c 690 static __always_inline int timer_shutdown(const int access, 2 timer-fttmr010.c 105 int (*timer_shutdown)(struct clock_event_device *evt); 3 timer-sp804.c158 static inline void timer_shutdown(struct clock_event_device *evt) 4 timer.h 239 static inline int timer_shutdown(struct timer_list *timer) Guenter
Re: KUnit issues - Was: [igt-dev] [PATCH RFC v2 8/8] drm/i915: check if current->mm is not NULL
On Fri, Nov 4, 2022 at 12:50 AM Mauro Carvalho Chehab wrote: > > On Thu, 3 Nov 2022 15:43:26 -0700 > Daniel Latypov wrote: > > > On Thu, Nov 3, 2022 at 8:23 AM Mauro Carvalho Chehab > > wrote: > > > > > > Hi, > > > > > > I'm facing a couple of issues when testing KUnit with the i915 driver. > > > > > > The DRM subsystem and the i915 driver has, for a long time, his own > > > way to do unit tests, which seems to be added before KUnit. > > > > > > I'm now checking if it is worth start using KUnit at i915. So, I wrote > > > a RFC with some patches adding support for the tests we have to be > > > reported using Kernel TAP and KUnit. > > > > > > There are basically 3 groups of tests there: > > > > > > - mock tests - check i915 hardware-independent logic; > > > - live tests - run some hardware-specific tests; > > > - perf tests - check perf support - also hardware-dependent. > > > > > > As they depend on i915 driver, they run only on x86, with PCI > > > stack enabled, but the mock tests run nicely via qemu. > > > > > > The live and perf tests require a real hardware. As we run them > > > together with our CI, which, among other things, test module > > > unload/reload and test loading i915 driver with different > > > modprobe parameters, the KUnit tests should be able to run as > > > a module. > > > > > > While testing KUnit, I noticed a couple of issues: > > > > > > 1. kunit.py parser is currently broken when used with modules > > > > > > the parser expects "TAP version xx" output, but this won't > > > happen when loading the kunit test driver. > > > > > > Are there any plans or patches fixing this issue? > > > > Partially. > > Note: we need a header to look for so we can strip prefixes (like > > timestamps). > > > > But there is a patch in the works to add a TAP header for each > > subtest, hopefully in time for 6.2. > > Good to know. > > > This is to match the KTAP spec: > > https://kernel.org/doc/html/latest/dev-tools/ktap.html > > I see. > > > That should fix it so you can parse one suite's results at a time. > > I'm pretty sure it won't fix the case where there's multiple suites > > and/or you're trying to parse all test results at once via > > > > $ find /sys/kernel/debug/kunit/ -type f | xargs cat | > > ./tools/testing/kunit/kunit.py parse > > Could you point me to the changeset? perhaps I can write a followup > patch addressing this case. rm...@google.com was working on them and should hopefully be able to send them out real soon. You should get CC'd on those. I think the follow-up work is just crafting an example parser input file and iterating until $ ./tools/testing/kunit/kunit.py parse < /tmp/example_input produces our desired results. > > > I think that in-kernel code change + some more python changes could > > make the above command work, but no one has actively started looking > > at that just yet. > > Hopefully we can pick this up and also get it done for 6.2 (unless I'm > > underestimating how complicated this is). > > > > > > > > 2. current->mm is not initialized > > > > > > Some tests do mmap(). They need the mm user context to be initialized, > > > but this is not happening right now. > > > > > > Are there a way to properly initialize it for KUnit? > > > > Right, this is a consequence of how early built-in KUnit tests are run > > after boot. > > I think for now, the answer is to make the test module-only. > > > > I know David had some ideas here, but I can't speak to them. > > This is happening when test-i915 is built as module as well. Oh, I didn't expect that at all. > > I suspect that the function which initializes it is mm_alloc() inside > kernel/fork.c: > > struct mm_struct *mm_alloc(void) > { > struct mm_struct *mm; > > mm = allocate_mm(); > if (!mm) > return NULL; > > memset(mm, 0, sizeof(*mm)); > return mm_init(mm, current, current_user_ns()); > } > > As modprobing a test won't fork until all tests run, this never runs. > > It seems that the normal usage is at fs/exec.c: > > fs/exec.c: bprm->mm = mm = mm_alloc(); > > but other places also call it: > > arch/arm/mach-rpc/ecard.c: struct mm_struct * mm = mm_alloc(); > drivers/dma-buf/dma-resv.c: struct mm_struct *mm = mm_alloc(); > include/linux/sched/mm.h:extern struct mm_struct *mm_alloc(void); > mm/debug_vm_pgtable.c: args->mm = mm_alloc(); > > Probably the solution would be to call it inside kunit executor code, > adding support for modules to use it. I know basically nothing about the mm code. I think I vaguely recall there being issues with this on UML or something, but I could be totally wrong. I'll wait for David to chime in when he can. > > > > 3. there's no test filters for modules > > > > > > In order to be able to do proper CI automation, it is needed to > > > be able to control what tests will run or not. That's specially > > > int
Re: [PATCH 2/2] drm/i915/mtl: Enable Idle Messaging for GSC CS
On 10/31/2022 8:36 PM, Badal Nilawar wrote: From: Vinay Belgaumkar By defaut idle mesaging is disabled for GSC CS so to unblock RC6 entry on media tile idle messaging need to be enabled. C6 entry instead of RC6. Also *needs*. Bspec: 71496 Cc: Daniele Ceraolo Spurio Signed-off-by: Vinay Belgaumkar Signed-off-by: Badal Nilawar --- drivers/gpu/drm/i915/gt/intel_engine_pm.c | 12 drivers/gpu/drm/i915/gt/intel_gt_regs.h | 3 +++ 2 files changed, 15 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/intel_engine_pm.c b/drivers/gpu/drm/i915/gt/intel_engine_pm.c index b0a4a2dbe3ee..8d391f8fd861 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_pm.c @@ -15,6 +15,7 @@ #include "intel_rc6.h" #include "intel_ring.h" #include "shmem_utils.h" +#include "intel_gt_regs.h" static void dbg_poison_ce(struct intel_context *ce) { @@ -271,10 +272,21 @@ static const struct intel_wakeref_ops wf_ops = { void intel_engine_init__pm(struct intel_engine_cs *engine) { + struct drm_i915_private *i915 = engine->i915; struct intel_runtime_pm *rpm = engine->uncore->rpm; intel_wakeref_init(&engine->wakeref, rpm, &wf_ops); intel_engine_init_heartbeat(engine); + + if (IS_METEORLAKE(i915) && engine->id == GSC0) { + intel_uncore_write(engine->gt->uncore, + RC_PSMI_CTRL_GSCCS, + _MASKED_BIT_DISABLE(IDLE_MSG_DISABLE)); + drm_dbg(&i915->drm, + "Set GSC CS Idle Reg to: 0x%x", + intel_uncore_read(engine->gt->uncore, RC_PSMI_CTRL_GSCCS)); Do we need the debug print here? + } + } /** diff --git a/drivers/gpu/drm/i915/gt/intel_gt_regs.h b/drivers/gpu/drm/i915/gt/intel_gt_regs.h index f4624262dc81..176902a9f2a2 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_regs.h +++ b/drivers/gpu/drm/i915/gt/intel_gt_regs.h @@ -908,6 +908,9 @@ #define MSG_IDLE_FW_MASK REG_GENMASK(13, 9) #define MSG_IDLE_FW_SHIFT9 +#define RC_PSMI_CTRL_GSCCS _MMIO(0x11a050) +#define IDLE_MSG_DISABLE BIT(0) Is the alignment off? Thanks, Vinay. + #define FORCEWAKE_MEDIA_GEN9 _MMIO(0xa270) #define FORCEWAKE_RENDER_GEN9 _MMIO(0xa278)
Re: [RFC][PATCH v3 13/33] timers: drm: Use timer_shutdown_sync() before freeing timer
On Fri, 4 Nov 2022 08:48:28 + Tvrtko Ursulin wrote: > If it stays all DRM drivers in one patch then I guess it needs to go via > drm-misc, which for i915 would be okay I think in this case since patch > is extremely unlikely to clash with anything. Or split it up per driver > and then we can handle it in drm-intel-next once core functionality is in. > > We do however have some more calls to del_timer_sync, where freeing is > perhaps not immediately next to the site in code, but things definitely > get freed like on module unload. Would we need to convert all of them to > avoid some, presumably new, warnings? I'm happy to split this patch up. I just got a bit lazy and started just grouping via entire subsystems. You should see the networking patch ;-) -- Steve
Re: [PATCH v2 1/2] drm/i915/guc: Properly initialise kernel contexts
On 11/4/2022 11:53, Ceraolo Spurio, Daniele wrote: On 11/2/2022 12:21 PM, john.c.harri...@intel.com wrote: From: John Harrison If a context has already been registered prior to first submission then context init code was not being called. The noticeable effect of that was the scheduling priority was left at zero (meaning super high priority) instead of being set to normal. This would occur with kernel contexts at start of day as they are manually pinned up front rather than on first submission. So add a call to initialise those when they are pinned. Does this need a fixes tag? on one side, we were leaving the priority to the wrong value, but on the other there were no actual consequences. I think that's the point. There was no actual issue, it's just a theoretical problem. So there is nothing to be gained by pushing this as a fix. It it seems like it would be a lot of unnecessary effort to push it all the way back to 5.17. John. Reviewed-by: Daniele Ceraolo Spurio Daniele Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 3 +++ 1 file changed, 3 insertions(+) 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 4ccb29f9ac55c..941613be3b9dd 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -4111,6 +4111,9 @@ static inline void guc_kernel_context_pin(struct intel_guc *guc, if (context_guc_id_invalid(ce)) pin_guc_id(guc, ce); + if (!test_bit(CONTEXT_GUC_INIT, &ce->flags)) + guc_context_init(ce); + try_context_registration(ce, true); }
Re: [RFC][PATCH v3 12/33] timers: dma-buf: Use timer_shutdown_sync() before freeing timer
On Fri, 4 Nov 2022 08:15:53 +0100 Christian König wrote: > > index fb6e0a6ae2c9..5d3e7b503501 100644 > > --- a/drivers/dma-buf/st-dma-fence.c > > +++ b/drivers/dma-buf/st-dma-fence.c > > @@ -412,7 +412,7 @@ static int test_wait_timeout(void *arg) > > > > err = 0; > > err_free: > > - del_timer_sync(&wt.timer); > > + timer_shutdown_sync(&wt.timer); > > Mhm, what exactly is the benefit of renaming the function? > > Not that I'm against the change, but my thinking is more if there are > more functions which don't re-arm the time than those which do that then > why not forbid it in general? Timers are more often re-armed then not. I had to look for the locations where del_timer*() was called just before freeing, and other locations where they are freed later. I didn't rename del_timer_sync() to timer_shutdown_sync(), this version renamed the new "del_timer_shutdown()" to "timer_shutdown_sync()". Maybe I'm just confused at what you are asking. -- Steve
[linux-next:master] BUILD SUCCESS WITH WARNING 0cdb3579f1ee4c1e55acf8dfb0697b660067b1f8
tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git master branch HEAD: 0cdb3579f1ee4c1e55acf8dfb0697b660067b1f8 Add linux-next specific files for 20221104 Warning reports: https://lore.kernel.org/oe-kbuild-all/202211041320.coq8eelj-...@intel.com https://lore.kernel.org/oe-kbuild-all/202211041654.zcupre9o-...@intel.com Warning: (recently discovered and may have been fixed) drivers/gpu/drm/amd/amdgpu/../display/dc/core/dc.c:4878: warning: This comment starts with '/**', but isn't a kernel-doc comment. Refer Documentation/doc-guide/kernel-doc.rst drivers/gpu/drm/amd/amdgpu/../display/dc/core/dc_link_dp.c:5044:24: warning: implicit conversion from 'enum ' to 'enum dc_status' [-Wenum-conversion] drivers/gpu/drm/msm/hdmi/hdmi.c:244:1: warning: 'static' is not at beginning of declaration [-Wold-style-declaration] drivers/gpu/drm/msm/hdmi/hdmi.c:251:1: warning: 'static' is not at beginning of declaration [-Wold-style-declaration] Warning ids grouped by kconfigs: gcc_recent_errors |-- alpha-allyesconfig | |-- drivers-gpu-drm-amd-amdgpu-..-display-dc-core-dc.c:warning:This-comment-starts-with-but-isn-t-a-kernel-doc-comment.-Refer-Documentation-doc-guide-kernel-doc.rst | |-- drivers-gpu-drm-amd-amdgpu-..-display-dc-core-dc_link_dp.c:warning:implicit-conversion-from-enum-anonymous-to-enum-dc_status | `-- drivers-gpu-drm-msm-hdmi-hdmi.c:warning:static-is-not-at-beginning-of-declaration |-- arc-allyesconfig | |-- drivers-gpu-drm-amd-amdgpu-..-display-dc-core-dc.c:warning:This-comment-starts-with-but-isn-t-a-kernel-doc-comment.-Refer-Documentation-doc-guide-kernel-doc.rst | |-- drivers-gpu-drm-amd-amdgpu-..-display-dc-core-dc_link_dp.c:warning:implicit-conversion-from-enum-anonymous-to-enum-dc_status | `-- drivers-gpu-drm-msm-hdmi-hdmi.c:warning:static-is-not-at-beginning-of-declaration |-- arc-randconfig-r036-20221104 | `-- drivers-gpu-drm-amd-amdgpu-..-display-dc-core-dc_link_dp.c:warning:implicit-conversion-from-enum-anonymous-to-enum-dc_status |-- arc-randconfig-r043-20221104 | |-- drivers-gpu-drm-amd-amdgpu-..-display-dc-core-dc.c:warning:This-comment-starts-with-but-isn-t-a-kernel-doc-comment.-Refer-Documentation-doc-guide-kernel-doc.rst | `-- drivers-gpu-drm-amd-amdgpu-..-display-dc-core-dc_link_dp.c:warning:implicit-conversion-from-enum-anonymous-to-enum-dc_status |-- arm-allyesconfig | |-- drivers-gpu-drm-amd-amdgpu-..-display-dc-core-dc.c:warning:This-comment-starts-with-but-isn-t-a-kernel-doc-comment.-Refer-Documentation-doc-guide-kernel-doc.rst | |-- drivers-gpu-drm-amd-amdgpu-..-display-dc-core-dc_link_dp.c:warning:implicit-conversion-from-enum-anonymous-to-enum-dc_status | `-- drivers-gpu-drm-msm-hdmi-hdmi.c:warning:static-is-not-at-beginning-of-declaration |-- arm-defconfig | `-- drivers-gpu-drm-msm-hdmi-hdmi.c:warning:static-is-not-at-beginning-of-declaration |-- arm64-allyesconfig | |-- drivers-gpu-drm-amd-amdgpu-..-display-dc-core-dc.c:warning:This-comment-starts-with-but-isn-t-a-kernel-doc-comment.-Refer-Documentation-doc-guide-kernel-doc.rst | |-- drivers-gpu-drm-amd-amdgpu-..-display-dc-core-dc_link_dp.c:warning:implicit-conversion-from-enum-anonymous-to-enum-dc_status | `-- drivers-gpu-drm-msm-hdmi-hdmi.c:warning:static-is-not-at-beginning-of-declaration |-- i386-allyesconfig | |-- drivers-gpu-drm-amd-amdgpu-..-display-dc-core-dc.c:warning:This-comment-starts-with-but-isn-t-a-kernel-doc-comment.-Refer-Documentation-doc-guide-kernel-doc.rst | `-- drivers-gpu-drm-amd-amdgpu-..-display-dc-core-dc_link_dp.c:warning:implicit-conversion-from-enum-anonymous-to-enum-dc_status |-- ia64-allmodconfig | |-- drivers-gpu-drm-amd-amdgpu-..-display-dc-core-dc.c:warning:This-comment-starts-with-but-isn-t-a-kernel-doc-comment.-Refer-Documentation-doc-guide-kernel-doc.rst | `-- drivers-gpu-drm-amd-amdgpu-..-display-dc-core-dc_link_dp.c:warning:implicit-conversion-from-enum-anonymous-to-enum-dc_status |-- ia64-buildonly-randconfig-r006-20221104 | |-- drivers-gpu-drm-amd-amdgpu-..-display-dc-core-dc.c:warning:This-comment-starts-with-but-isn-t-a-kernel-doc-comment.-Refer-Documentation-doc-guide-kernel-doc.rst | `-- drivers-gpu-drm-amd-amdgpu-..-display-dc-core-dc_link_dp.c:warning:implicit-conversion-from-enum-anonymous-to-enum-dc_status |-- m68k-allmodconfig | `-- drivers-gpu-drm-msm-hdmi-hdmi.c:warning:static-is-not-at-beginning-of-declaration |-- m68k-allyesconfig | `-- drivers-gpu-drm-msm-hdmi-hdmi.c:warning:static-is-not-at-beginning-of-declaration |-- mips-allyesconfig | |-- drivers-gpu-drm-amd-amdgpu-..-display-dc-core-dc.c:warning:This-comment-starts-with-but-isn-t-a-kernel-doc-comment.-Refer-Documentation-doc-guide-kernel-doc.rst | |-- drivers-gpu-drm-amd-amdgpu-..-display-dc-core-dc_link_dp.c:warning:implicit-conversion-from-enum-anonymous-to-enum-dc_status | `-- drivers-gpu-drm-msm-hdmi-hdmi.c:warning:static-is-not-at-beginning-o
Re: [PATCH v2 1/2] drm/i915/guc: Properly initialise kernel contexts
On 11/2/2022 12:21 PM, john.c.harri...@intel.com wrote: From: John Harrison If a context has already been registered prior to first submission then context init code was not being called. The noticeable effect of that was the scheduling priority was left at zero (meaning super high priority) instead of being set to normal. This would occur with kernel contexts at start of day as they are manually pinned up front rather than on first submission. So add a call to initialise those when they are pinned. Does this need a fixes tag? on one side, we were leaving the priority to the wrong value, but on the other there were no actual consequences. Reviewed-by: Daniele Ceraolo Spurio Daniele Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 3 +++ 1 file changed, 3 insertions(+) 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 4ccb29f9ac55c..941613be3b9dd 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -4111,6 +4111,9 @@ static inline void guc_kernel_context_pin(struct intel_guc *guc, if (context_guc_id_invalid(ce)) pin_guc_id(guc, ce); + if (!test_bit(CONTEXT_GUC_INIT, &ce->flags)) + guc_context_init(ce); + try_context_registration(ce, true); }
Re: [PATCH 1/2] drm/radeon: Using unsigned long instead of unsigned to fix possible overflow
On Fri, Nov 4, 2022 at 6:05 AM Hanjun Guo wrote: > > VBIOSImageOffset in struct UEFI_ACPI_VFCT is ULONG (unsigned long), > but it will be assigned to "unsigned offset", so use unsigned long > instead of unsigned for the offset, to avoid possible overflow. ULONG in atombios is 32 bits so an int should be fine. Alex > > Signed-off-by: Hanjun Guo > --- > drivers/gpu/drm/radeon/radeon_bios.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/radeon/radeon_bios.c > b/drivers/gpu/drm/radeon/radeon_bios.c > index 3312165..520d1d6 100644 > --- a/drivers/gpu/drm/radeon/radeon_bios.c > +++ b/drivers/gpu/drm/radeon/radeon_bios.c > @@ -611,7 +611,7 @@ static bool radeon_acpi_vfct_bios(struct radeon_device > *rdev) > struct acpi_table_header *hdr; > acpi_size tbl_size; > UEFI_ACPI_VFCT *vfct; > - unsigned offset; > + unsigned long offset; > > if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr))) > return false; > -- > 1.7.12.4 >
Re: [PATCH drm-misc-next v4 0/4] drm/arm/hdlcd: use drm managed resources
On Wed, Oct 26, 2022 at 05:34:27PM +0200, Danilo Krummrich wrote: > Hi, Hi Danilo, > > This patch series converts the driver to use drm managed resources to prevent > potential use-after-free issues on driver unbind/rebind and to get rid of the > usage of deprecated APIs. > > Changes in v2: > - drop patch "drm/arm/hdlcd: crtc: use drmm_crtc_init_with_planes()" > > Changes in v3: > - Fix alternate return paths in srcu read-side critical sections causing a > stall when unregistering the driver. > - Fix potential null pointer dereference in hdlcd_crtc_cleanup() introduced > dropping the patch in v2. > - Add a patch to remove explicit calls to drm_mode_config_cleanup(). > > Changes in v4: > - Remove patches to protect platform device bound resources with > drm_dev_{enter,exit}, since this would leave the hardware enabled when > regularly unloading the driver e.g. via rmmod. > Instead do this in a later series, once we got drm_dev_unplug() in place > to deal with a regular driver shutdown. This series is in a much better shape compared to the existing status quo. rmmod works without any issue and I can re-insmod the driver again. The only issue that I'm seeing that is not critical is that at reboot/shutdown time I'm getting an "Unexpected global fault, this could be serious" from the smmu: [ 6893.467910] arm-smmu 7fb3.iommu: disabling translation [ 6893.473550] ohci-platform 7ffb.usb: Removing from iommu group 1 [ 6893.479909] ehci-platform 7ffc.usb: Removing from iommu group 1 [ 6893.486931] arm-smmu 7fb1.iommu: disabling translation [ 6893.492521] hdlcd 7ff5.hdlcd: Removing from iommu group 3 [ 6893.492650] arm-smmu 7fb1.iommu: Unexpected global fault, this could be serious [ 6893.505959] arm-smmu 7fb1.iommu: GFSR 0x8001, GFSYNR0 0x, GFSYNR1 0x, GFSYNR2 0x [ 6893.516511] arm-smmu 7fb0.iommu: disabling translation [ 6893.522195] dma-pl330 7ff0.dma-controller: Removing from iommu group 2 [ 6893.529607] arm-smmu 2b50.iommu: disabling translation [ 6893.535221] pcieport :00:00.0: Removing from iommu group 0 [ 6893.541135] pci :01:00.0: Removing from iommu group 0 [ 6893.546604] pcieport :02:01.0: Removing from iommu group 0 [ 6893.552511] pcieport :02:02.0: Removing from iommu group 0 [ 6893.558418] pcieport :02:03.0: Removing from iommu group 0 [ 6893.564329] pcieport :02:0c.0: Removing from iommu group 0 [ 6893.570393] pcieport :02:10.0: Removing from iommu group 0 [ 6893.576314] pcieport :02:1f.0: Removing from iommu group 0 [ 6893.582214] sata_sil24 :03:00.0: Removing from iommu group 0 [ 6893.588270] sky2 :08:00.0: Removing from iommu group 0 [ 6893.594616] reboot: Power down The reboot/shutdown succeeds, so I'm not too worried about it for now, but hope that this is something you'll keep in mind in the later series when you do drm_dev_unplug(). With that, for the whole series: Acked-by: Liviu Dudau Thanks for the patience and going through the series iterations with me. I can pull this series into drm-misc-next on Monday if you don't have any other plans. Best regards, Liviu > > Danilo Krummrich (4): > drm/arm/hdlcd: use drmm_* to allocate driver structures > drm/arm/hdlcd: replace drm->dev_private with drm_to_hdlcd_priv() > drm/arm/hdlcd: plane: use drm managed resources > drm/arm/hdlcd: remove calls to drm_mode_config_cleanup() > > drivers/gpu/drm/arm/hdlcd_crtc.c | 24 +++ > drivers/gpu/drm/arm/hdlcd_drv.c | 41 > drivers/gpu/drm/arm/hdlcd_drv.h | 2 ++ > 3 files changed, 32 insertions(+), 35 deletions(-) > > > base-commit: e1e7bc481d49c3e3ada11029ce0d9b85a0a539d7 > -- > 2.37.3 > -- | I would like to | | fix the world, | | but they're not | | giving me the | \ source code! / --- ¯\_(ツ)_/¯
Re: [PATCH v3 3/8] dt-bindings: display/msm: add support for the display on SM8450
On Fri, 04 Nov 2022 16:03:19 +0300, Dmitry Baryshkov wrote: > Add DPU and MDSS schemas to describe MDSS and DPU blocks on the Qualcomm > SM8450 platform. > > Signed-off-by: Dmitry Baryshkov > --- > .../bindings/display/msm/qcom,sm8450-dpu.yaml | 132 +++ > .../display/msm/qcom,sm8450-mdss.yaml | 347 ++ > 2 files changed, 479 insertions(+) > create mode 100644 > Documentation/devicetree/bindings/display/msm/qcom,sm8450-dpu.yaml > create mode 100644 > Documentation/devicetree/bindings/display/msm/qcom,sm8450-mdss.yaml > My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check' on your patch (DT_CHECKER_FLAGS is new in v5.13): yamllint warnings/errors: dtschema/dtc warnings/errors: ./Documentation/devicetree/bindings/display/msm/qcom,sm8450-mdss.yaml: Unable to find schema file matching $id: http://devicetree.org/schemas/display/msm/mdss-common.yaml ./Documentation/devicetree/bindings/display/msm/qcom,sm8450-dpu.yaml: Unable to find schema file matching $id: http://devicetree.org/schemas/display/msm/dpu-common.yaml /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/display/msm/qcom,sm8450-dpu.example.dtb: display-controller@ae01000: False schema does not allow {'compatible': ['qcom,sm8450-dpu'], 'reg': [[182456320, 585728], [183173120, 8200]], 'reg-names': ['mdp', 'vbif'], 'clocks': [[4294967295, 28], [4294967295, 29], [4294967295, 1], [4294967295, 63], [4294967295, 60], [4294967295, 75]], 'clock-names': ['bus', 'nrt_bus', 'iface', 'lut', 'core', 'vsync'], 'assigned-clocks': [[4294967295, 75]], 'assigned-clock-rates': [[1920]], 'operating-points-v2': [[1]], 'power-domains': [[4294967295, 6]], 'interrupts': [[0]], 'ports': {'#address-cells': [[1]], '#size-cells': [[0]], 'port@0': {'reg': [[0]], 'endpoint': {'remote-endpoint': [[4294967295]]}}, 'port@1': {'reg': [[1]], 'endpoint': {'remote-endpoint': [[4294967295]]}}}, 'opp-table': {'compatible': ['operating-points-v2'], 'phandle': [[1]], 'opp-17200': {'opp-hz': [[0], [17200]], 'required-opps': [[4294967295]]}, 'o pp-2': {'opp-hz': [[0], [2]], 'required-opps': [[4294967295]]}, 'opp-32500': {'opp-hz': [[0], [32500]], 'required-opps': [[4294967295]]}, 'opp-37500': {'opp-hz': [[0], [37500]], 'required-opps': [[4294967295]]}, 'opp-5': {'opp-hz': [[0], [5]], 'required-opps': [[4294967295]]}}, '$nodename': ['display-controller@ae01000']} From schema: /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/display/msm/qcom,sm8450-dpu.yaml /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/display/msm/qcom,sm8450-dpu.example.dtb: display-controller@ae01000: Unevaluated properties are not allowed ('interrupts', 'operating-points-v2', 'opp-table', 'ports', 'power-domains' were unexpected) From schema: /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/display/msm/qcom,sm8450-dpu.yaml /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/display/msm/qcom,sm8450-mdss.example.dtb: display-subsystem@ae0: False schema does not allow {'compatible': ['qcom,sm8450-mdss'], 'reg': [[182452224, 4096]], 'reg-names': ['mdss'], 'interconnects': [[4294967295, 14, 0, 4294967295, 3, 0], [4294967295, 14, 0, 4294967295, 3, 0]], 'interconnect-names': ['mdp0-mem', 'mdp1-mem'], 'resets': [[4294967295, 0]], 'power-domains': [[4294967295, 0]], 'clocks': [[4294967295, 1], [4294967295, 28], [4294967295, 29], [4294967295, 60]], 'clock-names': ['iface', 'bus', 'nrt_bus', 'core'], 'interrupts': [[0, 83, 4]], 'interrupt-controller': True, '#interrupt-cells': [[1]], 'iommus': [[4294967295, 10240, 1026]], '#address-cells': [[1]], '#size-cells': [[1]], 'ranges': True, 'display-controller@ae01000': {'compatible': ['qcom,sm8450-dpu'], 'reg': [[182456320, 585728], [183173120, 8200]], 'reg-names': ['mdp', 'vbif'], 'clocks': [[4294967295, 28], [4294967295, 29], [4294967295, 1], [4294967295, 63], [4294967295, 60], [4294967295, 75]], 'clock-names': ['bus', 'nrt_bus', 'iface', 'lut', 'core', 'vsync'], 'assigned-clocks': [[4294967295, 75]], 'assigned-clock-rates': [[1920]], 'operating-points-v2': [[1]], 'power-domains': [[4294967295, 6]], 'interrupts': [[0]], 'ports': {'#address-cells': [[1]], '#size-cells': [[0]], 'port@0': {'reg': [[0]], 'endpoint': {'remote-endpoint': [[2]], 'phandle': [[6]]}}, 'port@1': {'reg': [[1]], 'endpoint': {'remote-endpoint': [[3]], 'phandle': [[8]]}}}, 'opp-table': {'compatible': ['operating-points-v2'], 'phandle': [[1]], 'opp-17200': {'opp-hz': [[0], [17200]], 'required-opps': [[4294967295]]}, 'opp-2': {'opp-hz': [[0], [2]], 'required-opps': [[4294967295]]}, 'opp-32500': {'opp-hz': [[0], [32500]], 'required-opps': [[4294967295]]}, 'opp-37500': {'opp-hz': [[0], [37500]], 'required-opps': [[4294967295]]}, 'opp-5': {'opp-hz': [[0], [5]], 'requi
Re: [PATCH v2] drm/i915/mtl: Add Wa_14017073508 for SAMedia
On Fri, Nov 04, 2022 at 12:15:59AM +0530, Badal Nilawar wrote: > This workaround is added for Media tile of MTL A step. It is to help > pcode workaround which handles the hardware issue seen during package C2/C3 > transitions due to RC6 entry/exit transitions on Media tile. As a part of > workaround pcode expect kmd to send mailbox message "media busy" when > components of Media tile are in use and "media idle" otherwise. > As per workaround description gucrc need to be disabled so enabled > host based RC for Media tile. > > v2: > - Correct workaround id (Matt) > - Fix review comments (Rodrigo) > > Cc: Rodrigo Vivi > Cc: Radhakrishna Sripada > Cc: Vinay Belgaumkar > Cc: Chris Wilson > Signed-off-by: Badal Nilawar Reviewed-by: Rodrigo Vivi > --- > drivers/gpu/drm/i915/gt/intel_gt_pm.c | 27 +++ > drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c | 13 ++- > drivers/gpu/drm/i915/i915_drv.h | 4 > drivers/gpu/drm/i915/i915_reg.h | 9 > 4 files changed, 52 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.c > b/drivers/gpu/drm/i915/gt/intel_gt_pm.c > index f553e2173bda..833b7682643f 100644 > --- a/drivers/gpu/drm/i915/gt/intel_gt_pm.c > +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.c > @@ -19,10 +19,31 @@ > #include "intel_rc6.h" > #include "intel_rps.h" > #include "intel_wakeref.h" > +#include "intel_pcode.h" > #include "pxp/intel_pxp_pm.h" > > #define I915_GT_SUSPEND_IDLE_TIMEOUT (HZ / 2) > > +static void mtl_media_busy(struct intel_gt *gt) > +{ > + /* Wa_14017073508: mtl */ > + if (IS_MTL_GRAPHICS_STEP(gt->i915, P, STEP_A0, STEP_B0) && > + gt->type == GT_MEDIA) > + snb_pcode_write_p(gt->uncore, PCODE_MBOX_GT_STATE, > + PCODE_MBOX_GT_STATE_MEDIA_BUSY, > + PCODE_MBOX_GT_STATE_DOMAIN_MEDIA, 0); > +} > + > +static void mtl_media_idle(struct intel_gt *gt) > +{ > + /* Wa_14017073508: mtl */ > + if (IS_MTL_GRAPHICS_STEP(gt->i915, P, STEP_A0, STEP_B0) && > + gt->type == GT_MEDIA) > + snb_pcode_write_p(gt->uncore, PCODE_MBOX_GT_STATE, > + PCODE_MBOX_GT_STATE_MEDIA_NOT_BUSY, > + PCODE_MBOX_GT_STATE_DOMAIN_MEDIA, 0); > +} > + > static void user_forcewake(struct intel_gt *gt, bool suspend) > { > int count = atomic_read(>->user_wakeref); > @@ -70,6 +91,9 @@ static int __gt_unpark(struct intel_wakeref *wf) > > GT_TRACE(gt, "\n"); > > + /* Wa_14017073508: mtl */ > + mtl_media_busy(gt); > + > /* >* It seems that the DMC likes to transition between the DC states a lot >* when there are no connected displays (no active power domains) during > @@ -119,6 +143,9 @@ static int __gt_park(struct intel_wakeref *wf) > GEM_BUG_ON(!wakeref); > intel_display_power_put_async(i915, POWER_DOMAIN_GT_IRQ, wakeref); > > + /* Wa_14017073508: mtl */ > + mtl_media_idle(gt); > + > return 0; > } > > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c > index 8f8dd05835c5..b5855091cf6a 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c > @@ -11,9 +11,20 @@ > > static bool __guc_rc_supported(struct intel_guc *guc) > { > + struct intel_gt *gt = guc_to_gt(guc); > + > + /* > + * Wa_14017073508: mtl > + * Do not enable gucrc to avoid additional interrupts which > + * may disrupt pcode wa. > + */ > + if (IS_MTL_GRAPHICS_STEP(gt->i915, P, STEP_A0, STEP_B0) && > + gt->type == GT_MEDIA) > + return false; > + > /* GuC RC is unavailable for pre-Gen12 */ > return guc->submission_supported && > - GRAPHICS_VER(guc_to_gt(guc)->i915) >= 12; > + GRAPHICS_VER(gt->i915) >= 12; > } > > static bool __guc_rc_selected(struct intel_guc *guc) > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h > index 05b3300cc4ed..659b92382ff2 100644 > --- a/drivers/gpu/drm/i915/i915_drv.h > +++ b/drivers/gpu/drm/i915/i915_drv.h > @@ -740,6 +740,10 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, > #define IS_XEHPSDV_GRAPHICS_STEP(__i915, since, until) \ > (IS_XEHPSDV(__i915) && IS_GRAPHICS_STEP(__i915, since, until)) > > +#define IS_MTL_GRAPHICS_STEP(__i915, variant, since, until) \ > + (IS_SUBPLATFORM(__i915, INTEL_METEORLAKE, INTEL_SUBPLATFORM_##variant) > && \ > + IS_GRAPHICS_STEP(__i915, since, until)) > + > /* > * DG2 hardware steppings are a bit unusual. The hardware design was forked > to > * create three variants (G10, G11, and G12) which each have distinct > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h > index 765a10e0de88..23d732413919 100644 > --- a/drivers/gpu/drm/i915/i915_reg.h > +++ b/drivers/gpu/drm/i915/i915_reg.h > @
Re: [Intel-gfx] [PATCH] drm/i915: Don't wait forever in drop_caches
On 11/4/2022 03:01, Tvrtko Ursulin wrote: On 03/11/2022 19:16, John Harrison wrote: On 11/3/2022 02:38, Tvrtko Ursulin wrote: On 03/11/2022 09:18, Tvrtko Ursulin wrote: On 03/11/2022 01:33, John Harrison wrote: On 11/2/2022 07:20, Tvrtko Ursulin wrote: On 02/11/2022 12:12, Jani Nikula wrote: On Tue, 01 Nov 2022, john.c.harri...@intel.com wrote: From: John Harrison At the end of each test, IGT does a drop caches call via sysfs with sysfs? Sorry, that was meant to say debugfs. I've also been working on some sysfs IGT issues and evidently got my wires crossed! special flags set. One of the possible paths waits for idle with an infinite timeout. That causes problems for debugging issues when CI catches a "can't go idle" test failure. Best case, the CI system times out (after 90s), attempts a bunch of state dump actions and then reboots the system to recover it. Worst case, the CI system can't do anything at all and then times out (after 1000s) and simply reboots. Sometimes a serial port log of dmesg might be available, sometimes not. So rather than making life hard for ourselves, change the timeout to be 10s rather than infinite. Also, trigger the standard wedge/reset/recover sequence so that testing can continue with a working system (if possible). Signed-off-by: John Harrison --- drivers/gpu/drm/i915/i915_debugfs.c | 7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index ae987e92251dd..9d916fbbfc27c 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -641,6 +641,9 @@ DEFINE_SIMPLE_ATTRIBUTE(i915_perf_noa_delay_fops, DROP_RESET_ACTIVE | \ DROP_RESET_SEQNO | \ DROP_RCU) + +#define DROP_IDLE_TIMEOUT (HZ * 10) I915_IDLE_ENGINES_TIMEOUT is defined in i915_drv.h. It's also only used here. So move here, dropping i915 prefix, next to the newly proposed one? Sure, can do that. I915_GEM_IDLE_TIMEOUT is defined in i915_gem.h. It's only used in gt/intel_gt.c. Move there and rename to GT_IDLE_TIMEOUT? I915_GT_SUSPEND_IDLE_TIMEOUT is defined and used only in intel_gt_pm.c. No action needed, maybe drop i915 prefix if wanted. These two are totally unrelated and in code not being touched by this change. I would rather not conflate changing random other things with fixing this specific issue. I915_IDLE_ENGINES_TIMEOUT is in ms, the rest are in jiffies. Add _MS suffix if wanted. My head spins. I follow and raise that the newly proposed DROP_IDLE_TIMEOUT applies to DROP_ACTIVE and not only DROP_IDLE. My original intention for the name was that is the 'drop caches timeout for intel_gt_wait_for_idle'. Which is quite the mouthful and hence abbreviated to DROP_IDLE_TIMEOUT. But yes, I realised later that name can be conflated with the DROP_IDLE flag. Will rename. Things get refactored, code moves around, bits get left behind, who knows. No reason to get too worked up. :) As long as people are taking a wider view when touching the code base, and are not afraid to send cleanups, things should be good. On the other hand, if every patch gets blocked in code review because someone points out some completely unrelated piece of code could be a bit better then nothing ever gets fixed. If you spot something that you think should be improved, isn't the general idea that you should post a patch yourself to improve it? There's two maintainers per branch and an order of magnitude or two more developers so it'd be nice if cleanups would just be incoming on self-initiative basis. ;) For the actual functional change at hand - it would be nice if code paths in question could handle SIGINT and then we could punt the decision on how long someone wants to wait purely to userspace. But it's probably hard and it's only debugfs so whatever. The code paths in question will already abort on a signal won't they? Both intel_gt_wait_for_idle() and intel_guc_wait_for_pending_msg(), which is where the uc_wait_for_idle eventually ends up, have an 'if(signal_pending) return -EINTR;' check. Beyond that, it sounds like what you are asking for is a change in the IGT libraries and/or CI framework to start sending signals after some specific timeout. That seems like a significantly more complex change (in terms of the number of entities affected and number of groups involved) and unnecessary. If you say so, I haven't looked at them all. But if the code path in question already aborts on signals then I am not sure what is the patch fixing? I assumed you are trying to avoid the write stuck in D forever, which then prevents driver unload and everything, requiring the test runner to eventually reboot. If you say SIGINT works then you can already recover from userspace, no? Whether or not 10s is enough CI will hopefully tell us. I'd probably err on the side of safety and make it longer,
Re: [PATCH RESEND 00/13] Convert omapfb drivers to gpiod API
On 11/4/22 04:16, Dmitry Torokhov wrote: This series converts various OMAPFB drivers to use the newer gpiod API that respects line polarity specified in DTS. Unfortunately existing DTS files specify incorrect (active high) polarity for reset lines. As discussed in [1] we will not try to correct existing DTSes, but instead follow the path established by DRM drivers for the same components, and continue using inverted polarity in the FB drivers. [1] https://lore.kernel.org/all/20221004213503.848262-1-dmitry.torok...@gmail.com/ To: Helge Deller To: Tony Lindgren To: Tomi Valkeinen To: Sebastian Reichel Cc: linux-o...@vger.kernel.org Cc: linux-fb...@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Cc: linux-ker...@vger.kernel.org --- Dmitry Torokhov (13): omapfb: connector-hdmi: switch to using gpiod API omapfb: panel-sony-acx565akm: remove support for platform data omapfb: panel-sony-acx565akm: switch to using gpiod API omapfb: encoder-tfp410: switch to using gpiod API omapfb: panel-dsi-cm: switch to using gpiod API omapfb: panel-tpo-td043mtea1: switch to using gpiod API omapfb: panel-nec-nl8048hl11: switch to using gpiod API omapfb: panel-dpi: remove support for platform data omapfb: connector-analog-tv: remove support for platform data omapfb: encoder-opa362: fix included headers omapfb: panel-lgphilips-lb035q02: remove backlight GPIO handling omapfb: panel-tpo-td028ttec1: stop including gpio.h omapfb: panel-sharp-ls037v7dw01: fix included headers .../omap2/omapfb/displays/connector-analog-tv.c| 60 ++- .../fbdev/omap2/omapfb/displays/connector-hdmi.c | 49 +++-- .../fbdev/omap2/omapfb/displays/encoder-opa362.c | 4 +- .../fbdev/omap2/omapfb/displays/encoder-tfp410.c | 67 .../video/fbdev/omap2/omapfb/displays/panel-dpi.c | 83 ++- .../fbdev/omap2/omapfb/displays/panel-dsi-cm.c | 116 - .../omapfb/displays/panel-lgphilips-lb035q02.c | 21 +--- .../omap2/omapfb/displays/panel-nec-nl8048hl11.c | 72 - .../omapfb/displays/panel-sharp-ls037v7dw01.c | 3 +- .../omap2/omapfb/displays/panel-sony-acx565akm.c | 105 ++- .../omap2/omapfb/displays/panel-tpo-td028ttec1.c | 1 - .../omap2/omapfb/displays/panel-tpo-td043mtea1.c | 59 +++ include/video/omap-panel-data.h| 71 - 13 files changed, 170 insertions(+), 541 deletions(-) --- base-commit: 61c3426aca2c71052ddcd06c32e29d92304990fd change-id: 20221103-omapfb-gpiod-87ca2550bd90 series applied to fbdev git tree. Thanks! Helge
Re: [PATCH v2 5/5] drm/i915/mtl: don't expose GSC command streamer to the user
On Wed, Nov 02, 2022 at 10:10:47AM -0700, Daniele Ceraolo Spurio wrote: > There is no userspace user for this CS yet, we only need it for internal > kernel ops (e.g. HuC, PXP), so don't expose it. > > v2: even if it's not exposed, rename the engine so it is easier to > identify in the debug logs (Matt) > > Signed-off-by: Daniele Ceraolo Spurio > Cc: Matt Roper Reviewed-by: Matt Roper > --- > drivers/gpu/drm/i915/gt/intel_engine_user.c | 27 - > 1 file changed, 21 insertions(+), 6 deletions(-) > > diff --git a/drivers/gpu/drm/i915/gt/intel_engine_user.c > b/drivers/gpu/drm/i915/gt/intel_engine_user.c > index 79312b734690..cd4f1b126f75 100644 > --- a/drivers/gpu/drm/i915/gt/intel_engine_user.c > +++ b/drivers/gpu/drm/i915/gt/intel_engine_user.c > @@ -191,6 +191,15 @@ static void add_legacy_ring(struct legacy_ring *ring, > ring->instance++; > } > > +static void engine_rename(struct intel_engine_cs *engine, const char *name, > u16 instance) > +{ > + char old[sizeof(engine->name)]; > + > + memcpy(old, engine->name, sizeof(engine->name)); > + scnprintf(engine->name, sizeof(engine->name), "%s%u", name, instance); > + drm_dbg(&engine->i915->drm, "renamed %s to %s\n", old, engine->name); > +} > + > void intel_engines_driver_register(struct drm_i915_private *i915) > { > struct legacy_ring ring = {}; > @@ -206,11 +215,19 @@ void intel_engines_driver_register(struct > drm_i915_private *i915) > struct intel_engine_cs *engine = > container_of((struct rb_node *)it, typeof(*engine), >uabi_node); > - char old[sizeof(engine->name)]; > > if (intel_gt_has_unrecoverable_error(engine->gt)) > continue; /* ignore incomplete engines */ > > + /* > + * We don't want to expose the GSC engine to the users, but we > + * still rename it so it is easier to identify in the debug logs > + */ > + if (engine->id == GSC0) { > + engine_rename(engine, "gsc", 0); > + continue; > + } > + > GEM_BUG_ON(engine->class >= ARRAY_SIZE(uabi_classes)); > engine->uabi_class = uabi_classes[engine->class]; > > @@ -220,11 +237,9 @@ void intel_engines_driver_register(struct > drm_i915_private *i915) > i915->engine_uabi_class_count[engine->uabi_class]++; > > /* Replace the internal name with the final user facing name */ > - memcpy(old, engine->name, sizeof(engine->name)); > - scnprintf(engine->name, sizeof(engine->name), "%s%u", > - intel_engine_class_repr(engine->class), > - engine->uabi_instance); > - DRM_DEBUG_DRIVER("renamed %s to %s\n", old, engine->name); > + engine_rename(engine, > + intel_engine_class_repr(engine->class), > + engine->uabi_instance); > > rb_link_node(&engine->uabi_node, prev, p); > rb_insert_color(&engine->uabi_node, &i915->uabi_engines); > -- > 2.37.3 > -- Matt Roper Graphics Software Engineer VTT-OSGC Platform Enablement Intel Corporation
[PATCH 0/2] Add GT oriented dmesg output
From: John Harrison When trying to analyse bug reports from CI, customers, etc. it can be difficult to work out exactly what is happening on which GT in a multi-GT system. So add GT oriented debug/error message wrappers. If used instead of the drm_ equivalents, you get the same output but with a GT# prefix on it. This patch also updates the gt/uc files to use the new helpers as a first step. The intention would be to convert all output messages that have access to a GT structure. Signed-off-by: John Harrison John Harrison (2): drm/i915/gt: Add GT oriented dmesg output drm/i915/uc: Update the gt/uc code to use GT_ERR and friends drivers/gpu/drm/i915/gt/intel_gt.h| 15 +++ drivers/gpu/drm/i915/gt/uc/intel_guc.c| 25 +++-- drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c| 9 +- .../gpu/drm/i915/gt/uc/intel_guc_capture.c| 50 -- drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 9 +- drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c | 17 ++-- drivers/gpu/drm/i915/gt/uc/intel_guc_log.c| 49 +- drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c | 3 +- drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 6 +- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 56 ++-- drivers/gpu/drm/i915/gt/uc/intel_huc.c| 20 ++-- drivers/gpu/drm/i915/gt/uc/intel_uc.c | 84 - drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c | 91 +-- drivers/gpu/drm/i915/gt/uc/selftest_guc.c | 36 .../drm/i915/gt/uc/selftest_guc_hangcheck.c | 22 ++--- .../drm/i915/gt/uc/selftest_guc_multi_lrc.c | 10 +- 16 files changed, 243 insertions(+), 259 deletions(-) -- 2.37.3
[PATCH 2/2] drm/i915/uc: Update the gt/uc code to use GT_ERR and friends
From: John Harrison Use the new GT oriented output message helpers where possible. Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/uc/intel_guc.c| 25 +++-- drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c| 9 +- .../gpu/drm/i915/gt/uc/intel_guc_capture.c| 50 -- drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 9 +- drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c | 17 ++-- drivers/gpu/drm/i915/gt/uc/intel_guc_log.c| 49 +- drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c | 3 +- drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 6 +- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 56 ++-- drivers/gpu/drm/i915/gt/uc/intel_huc.c| 20 ++-- drivers/gpu/drm/i915/gt/uc/intel_uc.c | 84 - drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c | 91 +-- drivers/gpu/drm/i915/gt/uc/selftest_guc.c | 36 .../drm/i915/gt/uc/selftest_guc_hangcheck.c | 22 ++--- .../drm/i915/gt/uc/selftest_guc_multi_lrc.c | 10 +- 15 files changed, 228 insertions(+), 259 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c index 27b09ba1d295f..36983a2cc20e8 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c @@ -330,7 +330,7 @@ static void guc_init_params(struct intel_guc *guc) params[GUC_CTL_DEVID] = guc_ctl_devid(guc); for (i = 0; i < GUC_CTL_MAX_DWORDS; i++) - DRM_DEBUG_DRIVER("param[%2d] = %#x\n", i, params[i]); + GT_DBG(guc_to_gt(guc), "param[%2d] = %#x\n", i, params[i]); } /* @@ -475,8 +475,8 @@ void intel_guc_fini(struct intel_guc *guc) int intel_guc_send_mmio(struct intel_guc *guc, const u32 *request, u32 len, u32 *response_buf, u32 response_buf_size) { - struct drm_i915_private *i915 = guc_to_gt(guc)->i915; - struct intel_uncore *uncore = guc_to_gt(guc)->uncore; + struct intel_gt *gt = guc_to_gt(guc); + struct intel_uncore *uncore = gt->uncore; u32 header; int i; int ret; @@ -510,8 +510,7 @@ int intel_guc_send_mmio(struct intel_guc *guc, const u32 *request, u32 len, 10, 10, &header); if (unlikely(ret)) { timeout: - drm_err(&i915->drm, "mmio request %#x: no reply %x\n", - request[0], header); + GT_ERR(gt, "mmio request %#x: no reply %x\n", request[0], header); goto out; } @@ -532,8 +531,7 @@ int intel_guc_send_mmio(struct intel_guc *guc, const u32 *request, u32 len, if (FIELD_GET(GUC_HXG_MSG_0_TYPE, header) == GUC_HXG_TYPE_NO_RESPONSE_RETRY) { u32 reason = FIELD_GET(GUC_HXG_RETRY_MSG_0_REASON, header); - drm_dbg(&i915->drm, "mmio request %#x: retrying, reason %u\n", - request[0], reason); + GT_DBG(gt, "mmio request %#x: retrying, reason %u\n", request[0], reason); goto retry; } @@ -541,16 +539,14 @@ int intel_guc_send_mmio(struct intel_guc *guc, const u32 *request, u32 len, u32 hint = FIELD_GET(GUC_HXG_FAILURE_MSG_0_HINT, header); u32 error = FIELD_GET(GUC_HXG_FAILURE_MSG_0_ERROR, header); - drm_err(&i915->drm, "mmio request %#x: failure %x/%u\n", - request[0], error, hint); + GT_ERR(gt, "mmio request %#x: failure %x/%u\n", request[0], error, hint); ret = -ENXIO; goto out; } if (FIELD_GET(GUC_HXG_MSG_0_TYPE, header) != GUC_HXG_TYPE_RESPONSE_SUCCESS) { proto: - drm_err(&i915->drm, "mmio request %#x: unexpected reply %#x\n", - request[0], header); + GT_ERR(gt, "mmio request %#x: unexpected reply %#x\n", request[0], header); ret = -EPROTO; goto out; } @@ -592,9 +588,9 @@ int intel_guc_to_host_process_recv_msg(struct intel_guc *guc, msg = payload[0] & guc->msg_enabled_mask; if (msg & INTEL_GUC_RECV_MSG_CRASH_DUMP_POSTED) - drm_err(&guc_to_gt(guc)->i915->drm, "Received early GuC crash dump notification!\n"); + GT_ERR(guc_to_gt(guc), "Received early GuC crash dump notification!\n"); if (msg & INTEL_GUC_RECV_MSG_EXCEPTION) - drm_err(&guc_to_gt(guc)->i915->drm, "Received early GuC exception notification!\n"); + GT_ERR(guc_to_gt(guc), "Received early GuC exception notification!\n"); return 0; } @@ -648,7 +644,8 @@ int intel_guc_suspend(struct intel_guc *guc) */ ret = intel_guc_send_mmio(guc, action, ARRAY_SIZE(action), NULL, 0); if (ret) - DRM_ERROR("GuC suspend: RESET_CLIENT action failed with error %d!\n", ret); + GT_ERR(guc_to_gt(guc), +
[PATCH 1/2] drm/i915/gt: Add GT oriented dmesg output
From: John Harrison When trying to analyse bug reports from CI, customers, etc. it can be difficult to work out exactly what is happening on which GT in a multi-GT system. So add GT oriented debug/error message wrappers. If used instead of the drm_ equivalents, you get the same output but with a GT# prefix on it. Signed-off-by: John Harrison --- drivers/gpu/drm/i915/gt/intel_gt.h | 15 +++ 1 file changed, 15 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/intel_gt.h b/drivers/gpu/drm/i915/gt/intel_gt.h index e0365d5562484..1e016fb0117a4 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.h +++ b/drivers/gpu/drm/i915/gt/intel_gt.h @@ -13,6 +13,21 @@ struct drm_i915_private; struct drm_printer; +#define GT_ERR(_gt, _fmt, ...) \ + drm_err(&(_gt)->i915->drm, "GT%u: " _fmt, (_gt)->info.id, ##__VA_ARGS__) + +#define GT_WARN(_gt, _fmt, ...) \ + drm_warn(&(_gt)->i915->drm, "GT%u: " _fmt, (_gt)->info.id, ##__VA_ARGS__) + +#define GT_NOTICE(_gt, _fmt, ...) \ + drm_notice(&(_gt)->i915->drm, "GT%u: " _fmt, (_gt)->info.id, ##__VA_ARGS__) + +#define GT_INFO(_gt, _fmt, ...) \ + drm_info(&(_gt)->i915->drm, "GT%u: " _fmt, (_gt)->info.id, ##__VA_ARGS__) + +#define GT_DBG(_gt, _fmt, ...) \ + drm_dbg(&(_gt)->i915->drm, "GT%u: " _fmt, (_gt)->info.id, ##__VA_ARGS__) + #define GT_TRACE(gt, fmt, ...) do {\ const struct intel_gt *gt__ __maybe_unused = (gt); \ GEM_TRACE("%s " fmt, dev_name(gt__->i915->drm.dev), \ -- 2.37.3
Re: [PATCH v2 22/65] clk: davinci: da8xx-cfgchip: Add a determine_rate hook
On 11/4/22 8:17 AM, Maxime Ripard wrote: The Davinci DA8xxx cfgchip "clk48" clock implements a mux with a set_parent hook, but doesn't provide a determine_rate implementation. This is a bit odd, since set_parent() is there to, as its name implies, change the parent of a clock. However, the most likely candidate to trigger that parent change is a call to clk_set_rate(), with determine_rate() figuring out which parent is the best suited for a given rate. The other trigger would be a call to clk_set_parent(), but it's far less used, and it doesn't look like there's any obvious user for that clock. So, the set_parent hook is effectively unused, possibly because of an oversight. However, it could also be an explicit decision by the original author to avoid any reparenting but through an explicit call to clk_set_parent(). The latter case would be equivalent to setting the flag CLK_SET_RATE_NO_REPARENT, together with setting our determine_rate hook to __clk_mux_determine_rate(). Indeed, if no determine_rate implementation is provided, clk_round_rate() (through clk_core_round_rate_nolock()) will call itself on the parent if CLK_SET_RATE_PARENT is set, and will not change the clock rate otherwise. __clk_mux_determine_rate() has the exact same behavior when CLK_SET_RATE_NO_REPARENT is set. And if it was an oversight, then we are at least explicit about our behavior now and it can be further refined down the line. The parent is defined in the device tree and is not expected to change at runtime, so if I am understanding the patch correctly, setting the CLK_SET_RATE_NO_REPARENT flag seems correct. Signed-off-by: Maxime Ripard --- drivers/clk/davinci/da8xx-cfgchip.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/clk/davinci/da8xx-cfgchip.c b/drivers/clk/davinci/da8xx-cfgchip.c index c04276bc4051..4c1cc59bba53 100644 --- a/drivers/clk/davinci/da8xx-cfgchip.c +++ b/drivers/clk/davinci/da8xx-cfgchip.c @@ -565,6 +565,7 @@ static u8 da8xx_usb1_clk48_get_parent(struct clk_hw *hw) } static const struct clk_ops da8xx_usb1_clk48_ops = { + .determine_rate = __clk_mux_determine_rate, .set_parent = da8xx_usb1_clk48_set_parent, .get_parent = da8xx_usb1_clk48_get_parent, }; @@ -589,6 +590,7 @@ da8xx_cfgchip_register_usb1_clk48(struct device *dev, init.name = "usb1_clk48"; init.ops = &da8xx_usb1_clk48_ops; + init.flags = CLK_SET_RATE_NO_REPARENT; init.parent_names = parent_names; init.num_parents = 2;
Re: [PATCH v2 54/65] clk: da8xx: clk48: Switch to determine_rate
On 11/4/22 8:18 AM, Maxime Ripard wrote: The TI DA8xx USB0 clk48 clocks implements a mux with a set_parent hook, but doesn't provide a determine_rate implementation. This is a bit odd, since set_parent() is there to, as its name implies, change the parent of a clock. However, the most likely candidate to trigger that parent change is a call to clk_set_rate(), with determine_rate() figuring out which parent is the best suited for a given rate. The other trigger would be a call to clk_set_parent(), but it's far less used, and it doesn't look like there's any obvious user for that clock. So, the set_parent hook is effectively unused, possibly because of an oversight. However, it could also be an explicit decision by the original author to avoid any reparenting but through an explicit call to clk_set_parent(). The driver does implement round_rate() though, which means that we can change the rate of the clock, but we will never get to change the parent. However, It's hard to tell whether it's been done on purpose or not. Since we'll start mandating a determine_rate() implementation, let's convert the round_rate() implementation to a determine_rate(), which will also make the current behavior explicit. And if it was an oversight, the clock behaviour can be adjusted later on. I think this one should be the same as the clk:davinci changes and not allow re-parenting. Since this is a USB 48MHz PHY clock, a rate change will never be requested. Signed-off-by: Maxime Ripard --- drivers/clk/davinci/da8xx-cfgchip.c | 10 ++ 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/clk/davinci/da8xx-cfgchip.c b/drivers/clk/davinci/da8xx-cfgchip.c index 4c1cc59bba53..f60c97091818 100644 --- a/drivers/clk/davinci/da8xx-cfgchip.c +++ b/drivers/clk/davinci/da8xx-cfgchip.c @@ -462,10 +462,12 @@ static unsigned long da8xx_usb0_clk48_recalc_rate(struct clk_hw *hw, return 4800; } -static long da8xx_usb0_clk48_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) +static int da8xx_usb0_clk48_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { - return 4800; + req->rate = 4800; + + return 0; } static int da8xx_usb0_clk48_set_parent(struct clk_hw *hw, u8 index) @@ -494,7 +496,7 @@ static const struct clk_ops da8xx_usb0_clk48_ops = { .disable= da8xx_usb0_clk48_disable, .is_enabled = da8xx_usb0_clk48_is_enabled, .recalc_rate= da8xx_usb0_clk48_recalc_rate, - .round_rate = da8xx_usb0_clk48_round_rate, + .determine_rate = da8xx_usb0_clk48_determine_rate, .set_parent = da8xx_usb0_clk48_set_parent, .get_parent = da8xx_usb0_clk48_get_parent, };
Re: [PATCH v2 21/65] clk: davinci: da8xx-cfgchip: Add a determine_rate hook
On 11/4/22 8:17 AM, Maxime Ripard wrote: The Davinci DA8xxx cfgchip mux clock implements a mux with a set_parent hook, but doesn't provide a determine_rate implementation. This is a bit odd, since set_parent() is there to, as its name implies, change the parent of a clock. However, the most likely candidate to trigger that parent change is a call to clk_set_rate(), with determine_rate() figuring out which parent is the best suited for a given rate. The other trigger would be a call to clk_set_parent(), but it's far less used, and it doesn't look like there's any obvious user for that clock. So, the set_parent hook is effectively unused, possibly because of an oversight. However, it could also be an explicit decision by the original author to avoid any reparenting but through an explicit call to clk_set_parent(). The parent is defined in the device tree and is not expected to change at runtime, so if I am understanding the patch correctly, setting the CLK_SET_RATE_NO_REPARENT flag seems correct. The latter case would be equivalent to setting the flag CLK_SET_RATE_NO_REPARENT, together with setting our determine_rate hook to __clk_mux_determine_rate(). Indeed, if no determine_rate implementation is provided, clk_round_rate() (through clk_core_round_rate_nolock()) will call itself on the parent if CLK_SET_RATE_PARENT is set, and will not change the clock rate otherwise. __clk_mux_determine_rate() has the exact same behavior when CLK_SET_RATE_NO_REPARENT is set. And if it was an oversight, then we are at least explicit about our behavior now and it can be further refined down the line. Signed-off-by: Maxime Ripard --- drivers/clk/davinci/da8xx-cfgchip.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/clk/davinci/da8xx-cfgchip.c b/drivers/clk/davinci/da8xx-cfgchip.c index 4103d605e804..c04276bc4051 100644 --- a/drivers/clk/davinci/da8xx-cfgchip.c +++ b/drivers/clk/davinci/da8xx-cfgchip.c @@ -229,6 +229,7 @@ static u8 da8xx_cfgchip_mux_clk_get_parent(struct clk_hw *hw) } static const struct clk_ops da8xx_cfgchip_mux_clk_ops = { + .determine_rate = __clk_mux_determine_rate, .set_parent = da8xx_cfgchip_mux_clk_set_parent, .get_parent = da8xx_cfgchip_mux_clk_get_parent, }; @@ -251,7 +252,7 @@ da8xx_cfgchip_mux_clk_register(struct device *dev, init.ops = &da8xx_cfgchip_mux_clk_ops; init.parent_names = parent_names; init.num_parents = 2; - init.flags = 0; + init.flags = CLK_SET_RATE_NO_REPARENT; mux->hw.init = &init; mux->regmap = regmap;
Re: [RFC][PATCH v3 00/33] timers: Use timer_shutdown*() before freeing timers
On Thu, Nov 3, 2022 at 10:48 PM Steven Rostedt wrote: > > Ideally, I would have the first patch go into this rc cycle, which is mostly > non functional as it will allow the other patches to come in via the > respective > subsystems in the next merge window. Ack. I also wonder if we could do the completely trivially correct conversions immediately. I'm talking about the scripted ones where it's currently a "del_timer_sync()", and the very next action is freeing whatever data structure the timer is in (possibly with something like free_irq() in between - my point is that there's an unconditional free that is very clear and unambiguous), so that there is absolutely no question about whether they should use "timer_shutdown_sync()" or not. IOW, things like patches 03, 17 and 31, and at least parts others in this series. This series clearly has several much more complex cases that need actual real code review, and I think it would help to have the completely unambiguous cases out of the way, just to get rid of noise. So I'd take that first patch, and a scripted set of "this cannot change any semantics" patches early. Linus
Re: [PATCH v5 02/31] drm/i915: Don't register backlight when another backlight should be used (v2)
Hi Matthew, Rafael, On 10/27/22 14:09, Rafael J. Wysocki wrote: > On Thu, Oct 27, 2022 at 12:37 PM Hans de Goede wrote: >> >> Hi, >> >> On 10/27/22 11:52, Matthew Garrett wrote: >>> On Thu, Oct 27, 2022 at 11:39:38AM +0200, Hans de Goede wrote: >>> The *only* behavior which actually is new in 6.1 is the native GPU drivers now doing the equivalent of: if (acpi_video_get_backlight_type() != acpi_backlight_native) return; In their backlight register paths (i), which is causing the native backlight to disappear on your custom laptop setup and on Chromebooks (with the Chromebooks case being already solved I hope.). >>> >>> It's causing the backlight control to vanish on any machine that isn't >>> ((acpi_video || vendor interface) || !acpi). Most machines that fall >>> into that are either weird or Chromebooks or old, but there are machines >>> that fall into that. >> >> I acknowledge that their are machines that fall into this category, >> but I expect / hope there to be so few of them that we can just DMI >> quirk our way out if this. >> >> I believe the old group to be small because: >> >> 1. Generally speaking the "native" control method is usually not >> present on the really old (pre ACPI video spec) mobile GPUs. >> >> 2. On most old laptops I would still expect there to be a vendor >> interface too, and if both get registered standard desktop environments >> will prefer the vendor one, so then we need a native DMI quirk to >> disable the vendor interface anyways and we already have a bunch of >> those, so some laptops in this group are already covered by DMI quirks. >> >> And a fix for the Chromebook case is already in Linus' tree, which >> just leaves the weird case, of which there will hopefully be only >> a few. >> >> I do share your worry that this might break some machines, but >> the only way to really find out is to get this code out there >> I'm afraid. >> >> I have just written a blog post asking for people to check if >> their laptop might be affected; and to report various details >> to me of their laptop is affected: >> >> https://hansdegoede.dreamwidth.org/26548.html >> >> Lets wait and see how this goes. If I get (too) many reports then >> I will send a revert of the addition of the: >> >> if (acpi_video_get_backlight_type() != acpi_backlight_native) >> return; >> >> check to the i915 / radeon / amd / nouveau drivers. >> >> (And if I only get a couple of reports I will probably just submit >> DMI quirks for the affected models). > > Sounds reasonable to me, FWIW. I have received quite a few test reports as a result of my blogpost (and of the blogpost's mention in an arstechnica article). Long story short, Matthew, you are right. Quite a few laptop models will end up with an empty /sys/class/backlight because of the native backlight class devices no longer registering when acpi_video_backlight_use_native() returns false. I will submit a patch-set later today to fix this (by making cpi_video_backlight_use_native() always return true for now). More detailed summary/analysis of the received test reports: -30 unaffected models -The following laptop models: Acer Aspire 1640 Apple MacBook 2.1 Apple MacBook 4.1 Apple MacBook Pro 7.1 (uses nv_backligh instead of intel_backlight!) HP Compaq nc6120 IBM ThinkPad X40 System76 Starling Star1 All only have a native intel_backlight interface and the heuristics from acpi_video_get_backlight_type() return acpi_backlight_vendor there causing the changes in 6.1 to not register native backlights when acpi_video_backlight_use_native() returns false resulting in an empty /sys/class/backlight, breaking users ability to control their laptop panel's brightness. I will submit a patch to always make acpi_video_backlight_use_native() return true for now to work around this for 6.1. I do plan to try to re-introduce that change again later. First I need to change the heuristics to still native on more models so that on models where the native backlight is the only (working) entry they will return native. -The Dell N1410 has acpi_video support and acpi_osi_is_win8() returns false so acpi_video_get_backlight_type() returns acpi_video, but acpi_video fails to register a backlight device due to a_BCM eval error. The intel_backlight interface works fine, but this model is going to need a DMI-use-native-quirk to avoid intel_backlight disappearing when acpi_video_backlight_use_native() is changed back. -The following laptop models actually use a vendor backlight control method, while also having a native backlight entry under /sys/class/backlight: Asus EeePC 901 -> native backlight confirmed to also work Dell Latitude D610 -> native backlight confirmed to work better then vendor Sony Vaio PCG-FRV3 -> native backlight not tested Note these will keep working the same as before in 6.1, independent of the revert. I've tracked these seperatel
Re: [PATCH v4] dma-buf: fix racing conflict of dma_heap_add()
On 11/4/22 11:05 AM, Dawei Li wrote: Racing conflict could be: task A task B list_for_each_entry strcmp(h->name)) list_for_each_entry strcmp(h->name) kzallockzalloc .. . device_create device_create list_add list_add The root cause is that task B has no idea about the fact someone else(A) has inserted heap with same name when it calls list_add, so a potential collision occurs. Fixes: c02a81fba74f ("dma-buf: Add dma-buf heaps framework") Signed-off-by: Dawei Li LGTM, Thanks, Acked-by: Andrew Davis --- v1: https://lore.kernel.org/all/tycp286mb2323950197f60fc3473123b7ca...@tycp286mb2323.jpnp286.prod.outlook.com/ v1->v2: Narrow down locking scope, check the existence of heap before insertion, as suggested by Andrew Davis. v2->v3: Remove double checking. v3->v4: Minor coding style and patch formatting adjustment. --- drivers/dma-buf/dma-heap.c | 28 +++- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c index 8f5848aa144f..59d158873f4c 100644 --- a/drivers/dma-buf/dma-heap.c +++ b/drivers/dma-buf/dma-heap.c @@ -233,18 +233,6 @@ struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info) return ERR_PTR(-EINVAL); } - /* check the name is unique */ - mutex_lock(&heap_list_lock); - list_for_each_entry(h, &heap_list, list) { - if (!strcmp(h->name, exp_info->name)) { - mutex_unlock(&heap_list_lock); - pr_err("dma_heap: Already registered heap named %s\n", - exp_info->name); - return ERR_PTR(-EINVAL); - } - } - mutex_unlock(&heap_list_lock); - heap = kzalloc(sizeof(*heap), GFP_KERNEL); if (!heap) return ERR_PTR(-ENOMEM); @@ -283,13 +271,27 @@ struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info) err_ret = ERR_CAST(dev_ret); goto err2; } - /* Add heap to the list */ + mutex_lock(&heap_list_lock); + /* check the name is unique */ + list_for_each_entry(h, &heap_list, list) { + if (!strcmp(h->name, exp_info->name)) { + mutex_unlock(&heap_list_lock); + pr_err("dma_heap: Already registered heap named %s\n", + exp_info->name); + err_ret = ERR_PTR(-EINVAL); + goto err3; + } + } + + /* Add heap to the list */ list_add(&heap->list, &heap_list); mutex_unlock(&heap_list_lock); return heap; +err3: + device_destroy(dma_heap_class, heap->heap_devt); err2: cdev_del(&heap->heap_cdev); err1:
[PATCH v4] dma-buf: fix racing conflict of dma_heap_add()
Racing conflict could be: task A task B list_for_each_entry strcmp(h->name)) list_for_each_entry strcmp(h->name) kzallockzalloc .. . device_create device_create list_add list_add The root cause is that task B has no idea about the fact someone else(A) has inserted heap with same name when it calls list_add, so a potential collision occurs. Fixes: c02a81fba74f ("dma-buf: Add dma-buf heaps framework") Signed-off-by: Dawei Li --- v1: https://lore.kernel.org/all/tycp286mb2323950197f60fc3473123b7ca...@tycp286mb2323.jpnp286.prod.outlook.com/ v1->v2: Narrow down locking scope, check the existence of heap before insertion, as suggested by Andrew Davis. v2->v3: Remove double checking. v3->v4: Minor coding style and patch formatting adjustment. --- drivers/dma-buf/dma-heap.c | 28 +++- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c index 8f5848aa144f..59d158873f4c 100644 --- a/drivers/dma-buf/dma-heap.c +++ b/drivers/dma-buf/dma-heap.c @@ -233,18 +233,6 @@ struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info) return ERR_PTR(-EINVAL); } - /* check the name is unique */ - mutex_lock(&heap_list_lock); - list_for_each_entry(h, &heap_list, list) { - if (!strcmp(h->name, exp_info->name)) { - mutex_unlock(&heap_list_lock); - pr_err("dma_heap: Already registered heap named %s\n", - exp_info->name); - return ERR_PTR(-EINVAL); - } - } - mutex_unlock(&heap_list_lock); - heap = kzalloc(sizeof(*heap), GFP_KERNEL); if (!heap) return ERR_PTR(-ENOMEM); @@ -283,13 +271,27 @@ struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info) err_ret = ERR_CAST(dev_ret); goto err2; } - /* Add heap to the list */ + mutex_lock(&heap_list_lock); + /* check the name is unique */ + list_for_each_entry(h, &heap_list, list) { + if (!strcmp(h->name, exp_info->name)) { + mutex_unlock(&heap_list_lock); + pr_err("dma_heap: Already registered heap named %s\n", + exp_info->name); + err_ret = ERR_PTR(-EINVAL); + goto err3; + } + } + + /* Add heap to the list */ list_add(&heap->list, &heap_list); mutex_unlock(&heap_list_lock); return heap; +err3: + device_destroy(dma_heap_class, heap->heap_devt); err2: cdev_del(&heap->heap_cdev); err1: -- 2.25.1
Re: [PATCH v3 1/8] memory: tegra: Add API for retrieving carveout bounds
On 04/11/2022 15:48, Krzysztof Kozlowski wrote: On 04/11/2022 11:46, Jon Hunter wrote: On 04/11/2022 15:35, Krzysztof Kozlowski wrote: On 04/11/2022 11:33, Jon Hunter wrote: Hi Thierry, Krzysztof, On 24/10/2022 14:15, Thierry Reding wrote: On Tue, Sep 20, 2022 at 11:11:56AM +0300, Mikko Perttunen wrote: From: Mikko Perttunen On Tegra234 NVDEC firmware is loaded from a secure carveout, where it has been loaded by a bootloader. When booting NVDEC, we need to tell it the address of this firmware, which we can determine by checking the starting address of the carveout. As such, add an MC API to query the bounds of carveouts, and add related information on Tegra234. Signed-off-by: Mikko Perttunen --- v2: - Add check for 64-bit phys_addr_t. In practice phys_addr_t is always 64 bits where this runs, but it avoids warnings in compile test. --- drivers/memory/tegra/mc.c | 25 + drivers/memory/tegra/tegra234.c | 5 + include/soc/tegra/mc.h | 11 +++ 3 files changed, 41 insertions(+) Krzysztof, I've applied this to the same tree as the patch that uses it for now. Let me know if you want me to put this on a separate stable branch for you to pull in. Any update on this? What kind of update do you expect? Ha! I guess I should be more explicit :-) Well, I would like to see this change in -next and so I was hoping that you would respond to the above to indicate how you would like to pull this in. The change will be in next via Thierry. I do not have to pull this in. The maintainer which applies patches is responsible for: 1. Having his tree in linux-next, 2. Sending the patches to upstream maintainer (e.g. arm-soc, Linus) later in pull request. There is no job for me here, if I agree with Thierry. There would be a job if I needed a separate stable branch, but that I did not decide yet... Do you think I need to pull it? If so, why? No. Like I said I just want to get this into -next for testing. I had _wrongly_ assumed that Thierry was waiting on feedback from you. I see this is not the case and so let me check with Thierry where this is. Jon -- nvpublic
Re: [PATCH v2 43/65] ASoC: tlv320aic32x4: Add a determine_rate hook
On Fri, Nov 04, 2022 at 04:51:23PM +0100, Maxime Ripard wrote: > Just filling determine_rate if it's missing with > __clk_mux_determine_rate will possibly pick different parents, and I'm > fairly certain that this have never been tested on most platforms, and > will be completely broken. And I don't really want to play a game of > whack-a-mole adding that flag everywhere it turns out it's broken. Well, hopefully everyone for whom it's an issue currently will be objecting to this version of the change anyway so we'll either know where to set the flag or we'll get the whack-a-mole with the series being merged? signature.asc Description: PGP signature
[RFC] drm/msm: Boost on waits
From: Rob Clark Minimize interactive latency by boosting frequency when userspace is waiting on the GPU to finish. Signed-off-by: Rob Clark --- I did contemplate also boosting on dma_fence_wait(), but (a) that would require some extra plumbing thru gpu-sched, (b) that only captures a sub-set of wait-on-dma-fence patterns, and (c) waiting on a dma-fence doesn't always imply urgency (for ex, virglrenderer poll()ing on a dma- fence to know when to send a fence irq to VM guest). But the driver WAIT_FENCE and CPU_PREP ioctls map to things like glFinish() where it is pretty clear that there is something wishing the GPU would finish sooner. drivers/gpu/drm/msm/msm_drv.c | 7 +-- drivers/gpu/drm/msm/msm_gem.c | 6 ++ drivers/gpu/drm/msm/msm_gpu_devfreq.c | 2 +- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index c3b77b44b2aa..017a512982a2 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -894,7 +894,7 @@ static int msm_ioctl_gem_info(struct drm_device *dev, void *data, } static int wait_fence(struct msm_gpu_submitqueue *queue, uint32_t fence_id, - ktime_t timeout) + ktime_t timeout, struct msm_gpu *gpu) { struct dma_fence *fence; int ret; @@ -924,6 +924,9 @@ static int wait_fence(struct msm_gpu_submitqueue *queue, uint32_t fence_id, if (!fence) return 0; + if (!dma_fence_is_signaled(fence)) + msm_devfreq_boost(gpu, 2); + ret = dma_fence_wait_timeout(fence, true, timeout_to_jiffies(&timeout)); if (ret == 0) { ret = -ETIMEDOUT; @@ -956,7 +959,7 @@ static int msm_ioctl_wait_fence(struct drm_device *dev, void *data, if (!queue) return -ENOENT; - ret = wait_fence(queue, args->fence, to_ktime(args->timeout)); + ret = wait_fence(queue, args->fence, to_ktime(args->timeout), priv->gpu); msm_submitqueue_put(queue); diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index 1dee0d18abbb..fbda0e3a94f8 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -846,6 +846,12 @@ int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout) op & MSM_PREP_NOSYNC ? 0 : timeout_to_jiffies(timeout); long ret; + if (!dma_resv_test_signaled(obj->resv, dma_resv_usage_rw(write))) { + struct msm_drm_private *priv = obj->dev->dev_private; + + msm_devfreq_boost(priv->gpu, 2); + } + ret = dma_resv_wait_timeout(obj->resv, dma_resv_usage_rw(write), true, remain); if (ret == 0) diff --git a/drivers/gpu/drm/msm/msm_gpu_devfreq.c b/drivers/gpu/drm/msm/msm_gpu_devfreq.c index 85c443a37e4e..025940eb08d1 100644 --- a/drivers/gpu/drm/msm/msm_gpu_devfreq.c +++ b/drivers/gpu/drm/msm/msm_gpu_devfreq.c @@ -305,7 +305,7 @@ void msm_devfreq_boost(struct msm_gpu *gpu, unsigned factor) struct msm_gpu_devfreq *df = &gpu->devfreq; uint64_t freq; - if (!has_devfreq(gpu)) + if (!gpu || !has_devfreq(gpu)) return; freq = get_freq(gpu); -- 2.38.1
Re: [PATCH v2 43/65] ASoC: tlv320aic32x4: Add a determine_rate hook
Hi Mark, On Fri, Nov 04, 2022 at 03:44:53PM +, Mark Brown wrote: > On Fri, Nov 04, 2022 at 02:18:00PM +0100, Maxime Ripard wrote: > > > So, the set_parent hook is effectively unused, possibly because of an > > oversight. However, it could also be an explicit decision by the > > original author to avoid any reparenting but through an explicit call to > > clk_set_parent(). > > > The latter case would be equivalent to setting the flag > > CLK_SET_RATE_NO_REPARENT, together with setting our determine_rate hook > > to __clk_mux_determine_rate(). Indeed, if no determine_rate > > implementation is provided, clk_round_rate() (through > > clk_core_round_rate_nolock()) will call itself on the parent if > > CLK_SET_RATE_PARENT is set, and will not change the clock rate > > otherwise. __clk_mux_determine_rate() has the exact same behavior when > > CLK_SET_RATE_NO_REPARENT is set. > > > And if it was an oversight, then we are at least explicit about our > > behavior now and it can be further refined down the line. > > Given that the current approach involves patching every single user to > set a default implementation it feels like it might be more > straightforward to just have the clock API use that implementation if > none is defined - as you say there's already a flag to indicate the > unusual case where there's a solid reason to prevent reparenting. It > feels like the resulting API is more straightforward. That would be another solution indeed. The thing is, most places where determine_rate is missing seems to be oversight, and the flag is missing as well. Just filling determine_rate if it's missing with __clk_mux_determine_rate will possibly pick different parents, and I'm fairly certain that this have never been tested on most platforms, and will be completely broken. And I don't really want to play a game of whack-a-mole adding that flag everywhere it turns out it's broken. Maxime signature.asc Description: PGP signature
Re: [PATCH v3 1/8] memory: tegra: Add API for retrieving carveout bounds
On 04/11/2022 11:46, Jon Hunter wrote: > > On 04/11/2022 15:35, Krzysztof Kozlowski wrote: >> On 04/11/2022 11:33, Jon Hunter wrote: >>> Hi Thierry, Krzysztof, >>> >>> On 24/10/2022 14:15, Thierry Reding wrote: On Tue, Sep 20, 2022 at 11:11:56AM +0300, Mikko Perttunen wrote: > From: Mikko Perttunen > > On Tegra234 NVDEC firmware is loaded from a secure carveout, where it > has been loaded by a bootloader. When booting NVDEC, we need to tell it > the address of this firmware, which we can determine by checking the > starting address of the carveout. As such, add an MC API to query the > bounds of carveouts, and add related information on Tegra234. > > Signed-off-by: Mikko Perttunen > --- > v2: > - Add check for 64-bit phys_addr_t. In practice phys_addr_t > is always 64 bits where this runs, but it avoids warnings in > compile test. > --- >drivers/memory/tegra/mc.c | 25 + >drivers/memory/tegra/tegra234.c | 5 + >include/soc/tegra/mc.h | 11 +++ >3 files changed, 41 insertions(+) Krzysztof, I've applied this to the same tree as the patch that uses it for now. Let me know if you want me to put this on a separate stable branch for you to pull in. >>> >>> Any update on this? >> >> What kind of update do you expect? > > Ha! I guess I should be more explicit :-) > > Well, I would like to see this change in -next and so I was hoping that > you would respond to the above to indicate how you would like to pull > this in. The change will be in next via Thierry. I do not have to pull this in. The maintainer which applies patches is responsible for: 1. Having his tree in linux-next, 2. Sending the patches to upstream maintainer (e.g. arm-soc, Linus) later in pull request. There is no job for me here, if I agree with Thierry. There would be a job if I needed a separate stable branch, but that I did not decide yet... Do you think I need to pull it? If so, why? Best regards, Krzysztof
Re: [PATCH v3 1/8] memory: tegra: Add API for retrieving carveout bounds
On 04/11/2022 15:35, Krzysztof Kozlowski wrote: On 04/11/2022 11:33, Jon Hunter wrote: Hi Thierry, Krzysztof, On 24/10/2022 14:15, Thierry Reding wrote: On Tue, Sep 20, 2022 at 11:11:56AM +0300, Mikko Perttunen wrote: From: Mikko Perttunen On Tegra234 NVDEC firmware is loaded from a secure carveout, where it has been loaded by a bootloader. When booting NVDEC, we need to tell it the address of this firmware, which we can determine by checking the starting address of the carveout. As such, add an MC API to query the bounds of carveouts, and add related information on Tegra234. Signed-off-by: Mikko Perttunen --- v2: - Add check for 64-bit phys_addr_t. In practice phys_addr_t is always 64 bits where this runs, but it avoids warnings in compile test. --- drivers/memory/tegra/mc.c | 25 + drivers/memory/tegra/tegra234.c | 5 + include/soc/tegra/mc.h | 11 +++ 3 files changed, 41 insertions(+) Krzysztof, I've applied this to the same tree as the patch that uses it for now. Let me know if you want me to put this on a separate stable branch for you to pull in. Any update on this? What kind of update do you expect? Ha! I guess I should be more explicit :-) Well, I would like to see this change in -next and so I was hoping that you would respond to the above to indicate how you would like to pull this in. Cheers! Jon -- nvpublic
Re: [PATCH v2 43/65] ASoC: tlv320aic32x4: Add a determine_rate hook
On Fri, Nov 04, 2022 at 02:18:00PM +0100, Maxime Ripard wrote: > So, the set_parent hook is effectively unused, possibly because of an > oversight. However, it could also be an explicit decision by the > original author to avoid any reparenting but through an explicit call to > clk_set_parent(). > The latter case would be equivalent to setting the flag > CLK_SET_RATE_NO_REPARENT, together with setting our determine_rate hook > to __clk_mux_determine_rate(). Indeed, if no determine_rate > implementation is provided, clk_round_rate() (through > clk_core_round_rate_nolock()) will call itself on the parent if > CLK_SET_RATE_PARENT is set, and will not change the clock rate > otherwise. __clk_mux_determine_rate() has the exact same behavior when > CLK_SET_RATE_NO_REPARENT is set. > And if it was an oversight, then we are at least explicit about our > behavior now and it can be further refined down the line. Given that the current approach involves patching every single user to set a default implementation it feels like it might be more straightforward to just have the clock API use that implementation if none is defined - as you say there's already a flag to indicate the unusual case where there's a solid reason to prevent reparenting. It feels like the resulting API is more straightforward. signature.asc Description: PGP signature
Re: [PATCH v3 1/8] memory: tegra: Add API for retrieving carveout bounds
On 04/11/2022 11:33, Jon Hunter wrote: > Hi Thierry, Krzysztof, > > On 24/10/2022 14:15, Thierry Reding wrote: >> On Tue, Sep 20, 2022 at 11:11:56AM +0300, Mikko Perttunen wrote: >>> From: Mikko Perttunen >>> >>> On Tegra234 NVDEC firmware is loaded from a secure carveout, where it >>> has been loaded by a bootloader. When booting NVDEC, we need to tell it >>> the address of this firmware, which we can determine by checking the >>> starting address of the carveout. As such, add an MC API to query the >>> bounds of carveouts, and add related information on Tegra234. >>> >>> Signed-off-by: Mikko Perttunen >>> --- >>> v2: >>> - Add check for 64-bit phys_addr_t. In practice phys_addr_t >>>is always 64 bits where this runs, but it avoids warnings in >>>compile test. >>> --- >>> drivers/memory/tegra/mc.c | 25 + >>> drivers/memory/tegra/tegra234.c | 5 + >>> include/soc/tegra/mc.h | 11 +++ >>> 3 files changed, 41 insertions(+) >> >> Krzysztof, >> >> I've applied this to the same tree as the patch that uses it for now. >> Let me know if you want me to put this on a separate stable branch for >> you to pull in. > > Any update on this? What kind of update do you expect? Best regards, Krzysztof
Re: [PATCH v3 1/8] memory: tegra: Add API for retrieving carveout bounds
Hi Thierry, Krzysztof, On 24/10/2022 14:15, Thierry Reding wrote: On Tue, Sep 20, 2022 at 11:11:56AM +0300, Mikko Perttunen wrote: From: Mikko Perttunen On Tegra234 NVDEC firmware is loaded from a secure carveout, where it has been loaded by a bootloader. When booting NVDEC, we need to tell it the address of this firmware, which we can determine by checking the starting address of the carveout. As such, add an MC API to query the bounds of carveouts, and add related information on Tegra234. Signed-off-by: Mikko Perttunen --- v2: - Add check for 64-bit phys_addr_t. In practice phys_addr_t is always 64 bits where this runs, but it avoids warnings in compile test. --- drivers/memory/tegra/mc.c | 25 + drivers/memory/tegra/tegra234.c | 5 + include/soc/tegra/mc.h | 11 +++ 3 files changed, 41 insertions(+) Krzysztof, I've applied this to the same tree as the patch that uses it for now. Let me know if you want me to put this on a separate stable branch for you to pull in. Any update on this? Thanks! Jon -- nvpublic
Re: [PATCH v1 3/5] arm64: dts: qcom: sm8450-hdk: enable display hardware
On 04-11-22, 16:13, Dmitry Baryshkov wrote: > Enable MDSS/DPU/DSI0 on SM8450-HDK device. Note, there is no panel > configuration (yet). > > Signed-off-by: Dmitry Baryshkov > --- > arch/arm64/boot/dts/qcom/sm8450-hdk.dts | 18 ++ > 1 file changed, 18 insertions(+) > > diff --git a/arch/arm64/boot/dts/qcom/sm8450-hdk.dts > b/arch/arm64/boot/dts/qcom/sm8450-hdk.dts > index 38ccd44620d0..e1a4cf1ee51d 100644 > --- a/arch/arm64/boot/dts/qcom/sm8450-hdk.dts > +++ b/arch/arm64/boot/dts/qcom/sm8450-hdk.dts > @@ -442,3 +442,21 @@ &usb_1_qmpphy { > vdda-phy-supply = <&vreg_l6b_1p2>; > vdda-pll-supply = <&vreg_l1b_0p91>; > }; > + > +&mdss { > + status = "okay"; > +}; > + > +&mdss_mdp { > + status = "okay"; > +}; > + > +&dsi0 { > + status = "okay"; > + vdda-supply = <&vreg_l6b_1p2>; > +}; > + > +&dsi0_phy { > + status = "okay"; > + vdds-supply = <&vreg_l5b_0p88>; > +}; This is missing dispcc, please enable that node too. Also, sort this please > -- > 2.35.1 -- ~Vinod
[PATCH v3 2/2] drm/msm: Hangcheck progress detection
From: Rob Clark If the hangcheck timer expires, check if the fw's position in the cmdstream has advanced (changed) since last timer expiration, and allow it up to three additional "extensions" to it's alotted time. The intention is to continue to catch "shader stuck in a loop" type hangs quickly, but allow more time for things that are actually making forward progress. Because we need to sample the CP state twice to detect if there has not been progress, this also cuts the the timer's duration in half. v2: Fix typo (REG_A6XX_CP_CSQ_IB2_STAT), add comment v3: Only halve hangcheck timer duration for generations which support progress detection (hdanton); removed unused a5xx progress (without knowing how to adjust for data buffered in ROQ it is too likely to report a false negative) Signed-off-by: Rob Clark Reviewed-by: Akhil P Oommen --- drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 34 +++ drivers/gpu/drm/msm/msm_drv.c | 1 - drivers/gpu/drm/msm/msm_drv.h | 8 ++- drivers/gpu/drm/msm/msm_gpu.c | 31 +++- drivers/gpu/drm/msm/msm_gpu.h | 3 +++ drivers/gpu/drm/msm/msm_ringbuffer.h | 24 +++ 6 files changed, 98 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index 1ff605c18ee6..7fe60c65a1eb 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -1843,6 +1843,39 @@ static uint32_t a6xx_get_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring) return ring->memptrs->rptr = gpu_read(gpu, REG_A6XX_CP_RB_RPTR); } +static bool a6xx_progress(struct msm_gpu *gpu, struct msm_ringbuffer *ring) +{ + struct msm_cp_state cp_state = { + .ib1_base = gpu_read64(gpu, REG_A6XX_CP_IB1_BASE), + .ib2_base = gpu_read64(gpu, REG_A6XX_CP_IB2_BASE), + .ib1_rem = gpu_read(gpu, REG_A6XX_CP_IB1_REM_SIZE), + .ib2_rem = gpu_read(gpu, REG_A6XX_CP_IB2_REM_SIZE), + }; + bool progress; + + /* +* Adjust the remaining data to account for what has already been +* fetched from memory, but not yet consumed by the SQE. +* +* This is not *technically* correct, the amount buffered could +* exceed the IB size due to hw prefetching ahead, but: +* +* (1) We aren't trying to find the exact position, just whether +* progress has been made +* (2) The CP_REG_TO_MEM at the end of a submit should be enough +* to prevent prefetching into an unrelated submit. (And +* either way, at some point the ROQ will be full.) +*/ + cp_state.ib1_rem += gpu_read(gpu, REG_A6XX_CP_CSQ_IB1_STAT) >> 16; + cp_state.ib2_rem += gpu_read(gpu, REG_A6XX_CP_CSQ_IB2_STAT) >> 16; + + progress = !!memcmp(&cp_state, &ring->last_cp_state, sizeof(cp_state)); + + ring->last_cp_state = cp_state; + + return progress; +} + static u32 a618_get_speed_bin(u32 fuse) { if (fuse == 0) @@ -1961,6 +1994,7 @@ static const struct adreno_gpu_funcs funcs = { .create_address_space = a6xx_create_address_space, .create_private_address_space = a6xx_create_private_address_space, .get_rptr = a6xx_get_rptr, + .progress = a6xx_progress, }, .get_timestamp = a6xx_get_timestamp, }; diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 670651cdfa79..c3b77b44b2aa 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -419,7 +419,6 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv) priv->dev = ddev; priv->wq = alloc_ordered_workqueue("msm", 0); - priv->hangcheck_period = DRM_MSM_HANGCHECK_DEFAULT_PERIOD; INIT_LIST_HEAD(&priv->objects); mutex_init(&priv->obj_lock); diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 0609daf4fa4c..876d8d5eec2f 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -225,7 +225,13 @@ struct msm_drm_private { struct drm_atomic_state *pm_state; - /* For hang detection, in ms */ + /** +* hangcheck_period: For hang detection, in ms +* +* Note that in practice, a submit/job will get at least two hangcheck +* periods, due to checking for progress being implemented as simply +* "have the CP position registers changed since last time?" +*/ unsigned int hangcheck_period; /** diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 3dffee54a951..bfef659d3a5c 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -500,6 +500,21 @@ static void hangcheck_timer_reset(struct msm_gpu *gpu) round_jiffies_up(jiffies + msecs_to
[PATCH v3 1/2] drm/msm/adreno: Simplify read64/write64 helpers
From: Rob Clark The _HI reg is always following the _LO reg, so no need to pass these offsets seprately. Signed-off-by: Rob Clark Reviewed-by: Dmitry Baryshkov Reviewed-by: Akhil P Oommen --- drivers/gpu/drm/msm/adreno/a4xx_gpu.c | 3 +-- drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 27 - drivers/gpu/drm/msm/adreno/a5xx_preempt.c | 4 +-- drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 24 ++ drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c | 3 +-- drivers/gpu/drm/msm/msm_gpu.h | 12 - 6 files changed, 27 insertions(+), 46 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c index 7cb8d9849c07..a10feb8a4194 100644 --- a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c @@ -606,8 +606,7 @@ static int a4xx_pm_suspend(struct msm_gpu *gpu) { static int a4xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value) { - *value = gpu_read64(gpu, REG_A4XX_RBBM_PERFCTR_CP_0_LO, - REG_A4XX_RBBM_PERFCTR_CP_0_HI); + *value = gpu_read64(gpu, REG_A4XX_RBBM_PERFCTR_CP_0_LO); return 0; } diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c index 3dcec7acb384..ba22d3c918bc 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c @@ -605,11 +605,9 @@ static int a5xx_ucode_init(struct msm_gpu *gpu) a5xx_ucode_check_version(a5xx_gpu, a5xx_gpu->pfp_bo); } - gpu_write64(gpu, REG_A5XX_CP_ME_INSTR_BASE_LO, - REG_A5XX_CP_ME_INSTR_BASE_HI, a5xx_gpu->pm4_iova); + gpu_write64(gpu, REG_A5XX_CP_ME_INSTR_BASE_LO, a5xx_gpu->pm4_iova); - gpu_write64(gpu, REG_A5XX_CP_PFP_INSTR_BASE_LO, - REG_A5XX_CP_PFP_INSTR_BASE_HI, a5xx_gpu->pfp_iova); + gpu_write64(gpu, REG_A5XX_CP_PFP_INSTR_BASE_LO, a5xx_gpu->pfp_iova); return 0; } @@ -868,8 +866,7 @@ static int a5xx_hw_init(struct msm_gpu *gpu) * memory rendering at this point in time and we don't want to block off * part of the virtual memory space. */ - gpu_write64(gpu, REG_A5XX_RBBM_SECVID_TSB_TRUSTED_BASE_LO, - REG_A5XX_RBBM_SECVID_TSB_TRUSTED_BASE_HI, 0x); + gpu_write64(gpu, REG_A5XX_RBBM_SECVID_TSB_TRUSTED_BASE_LO, 0x); gpu_write(gpu, REG_A5XX_RBBM_SECVID_TSB_TRUSTED_SIZE, 0x); /* Put the GPU into 64 bit by default */ @@ -908,8 +905,7 @@ static int a5xx_hw_init(struct msm_gpu *gpu) return ret; /* Set the ringbuffer address */ - gpu_write64(gpu, REG_A5XX_CP_RB_BASE, REG_A5XX_CP_RB_BASE_HI, - gpu->rb[0]->iova); + gpu_write64(gpu, REG_A5XX_CP_RB_BASE, gpu->rb[0]->iova); /* * If the microcode supports the WHERE_AM_I opcode then we can use that @@ -936,7 +932,7 @@ static int a5xx_hw_init(struct msm_gpu *gpu) } gpu_write64(gpu, REG_A5XX_CP_RB_RPTR_ADDR, - REG_A5XX_CP_RB_RPTR_ADDR_HI, shadowptr(a5xx_gpu, gpu->rb[0])); + shadowptr(a5xx_gpu, gpu->rb[0])); } else if (gpu->nr_rings > 1) { /* Disable preemption if WHERE_AM_I isn't available */ a5xx_preempt_fini(gpu); @@ -1239,9 +1235,9 @@ static void a5xx_fault_detect_irq(struct msm_gpu *gpu) gpu_read(gpu, REG_A5XX_RBBM_STATUS), gpu_read(gpu, REG_A5XX_CP_RB_RPTR), gpu_read(gpu, REG_A5XX_CP_RB_WPTR), - gpu_read64(gpu, REG_A5XX_CP_IB1_BASE, REG_A5XX_CP_IB1_BASE_HI), + gpu_read64(gpu, REG_A5XX_CP_IB1_BASE), gpu_read(gpu, REG_A5XX_CP_IB1_BUFSZ), - gpu_read64(gpu, REG_A5XX_CP_IB2_BASE, REG_A5XX_CP_IB2_BASE_HI), + gpu_read64(gpu, REG_A5XX_CP_IB2_BASE), gpu_read(gpu, REG_A5XX_CP_IB2_BUFSZ)); /* Turn off the hangcheck timer to keep it from bothering us */ @@ -1427,8 +1423,7 @@ static int a5xx_pm_suspend(struct msm_gpu *gpu) static int a5xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value) { - *value = gpu_read64(gpu, REG_A5XX_RBBM_ALWAYSON_COUNTER_LO, - REG_A5XX_RBBM_ALWAYSON_COUNTER_HI); + *value = gpu_read64(gpu, REG_A5XX_RBBM_ALWAYSON_COUNTER_LO); return 0; } @@ -1465,8 +1460,7 @@ static int a5xx_crashdumper_run(struct msm_gpu *gpu, if (IS_ERR_OR_NULL(dumper->ptr)) return -EINVAL; - gpu_write64(gpu, REG_A5XX_CP_CRASH_SCRIPT_BASE_LO, - REG_A5XX_CP_CRASH_SCRIPT_BASE_HI, dumper->iova); + gpu_write64(gpu, REG_A5XX_CP_CRASH_SCRIPT_BASE_LO, dumper->iova); gpu_write(gpu, REG_A5XX_CP_CRASH_DUMP_CNTL, 1); @@ -1666,8 +1660,7 @@ static u64 a5xx_gpu_busy(struct msm_gpu *gpu, unsigned long *out_sample_rate) { u64 busy_cycles; - busy_cycles = gpu_read64(gpu, REG_A5XX_RBBM_P
[PATCH v3 0/2] drm/msm: Improved hang detection
From: Rob Clark Try to detect when submit jobs are making forward progress and give them a bit more time. Rob Clark (2): drm/msm/adreno: Simplify read64/write64 helpers drm/msm: Hangcheck progress detection drivers/gpu/drm/msm/adreno/a4xx_gpu.c | 3 +- drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 27 -- drivers/gpu/drm/msm/adreno/a5xx_preempt.c | 4 +- drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 58 +++-- drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c | 3 +- drivers/gpu/drm/msm/msm_drv.c | 1 - drivers/gpu/drm/msm/msm_drv.h | 8 ++- drivers/gpu/drm/msm/msm_gpu.c | 31 ++- drivers/gpu/drm/msm/msm_gpu.h | 15 +++--- drivers/gpu/drm/msm/msm_ringbuffer.h| 24 + 10 files changed, 125 insertions(+), 49 deletions(-) -- 2.38.1
Re: Try to address the DMA-buf coherency problem
Am 04.11.22 um 15:58 schrieb Rob Clark: On Wed, Nov 2, 2022 at 5:21 AM Christian König wrote: Hi Lucas, Am 02.11.22 um 12:39 schrieb Lucas Stach: Hi Christian, going to reply in more detail when I have some more time, so just some quick thoughts for now. Am Mittwoch, dem 02.11.2022 um 12:18 +0100 schrieb Christian König: Am 01.11.22 um 22:09 schrieb Nicolas Dufresne: [SNIP] As far as I can see it you guys just allocate a buffer from a V4L2 device, fill it with data and send it to Wayland for displaying. To be honest I'm really surprised that the Wayland guys hasn't pushed back on this practice already. This only works because the Wayland as well as X display pipeline is smart enough to insert an extra copy when it find that an imported buffer can't be used as a framebuffer directly. With bracketed access you could even make this case work, as the dGPU would be able to slurp a copy of the dma-buf into LMEM for scanout. Well, this copy is what we are trying to avoid here. The codec should pump the data into LMEM in the first place. For the dGPU VRAM case, shouldn't this be amdgpu re-importing it's own dmabuf, which more or less bypasses dma-buf to get back the backing GEM obj? When the codec and scanout is on the same device, then yes. But we already had cases where the codec was on the dGPU and scanout happened on the integrated engine. Regards, Christian. BR, -R
Re: [PATCH v2 56/65] clk: ingenic: cgu: Switch to determine_rate
Hi Paul, On Fri, Nov 04, 2022 at 02:31:20PM +, Paul Cercueil wrote: > Le ven. 4 nov. 2022 à 14:18:13 +0100, Maxime Ripard a > écrit : > > The Ingenic CGU clocks implements a mux with a set_parent hook, but > > doesn't provide a determine_rate implementation. > > > > This is a bit odd, since set_parent() is there to, as its name implies, > > change the parent of a clock. However, the most likely candidate to > > trigger that parent change is a call to clk_set_rate(), with > > determine_rate() figuring out which parent is the best suited for a > > given rate. > > > > The other trigger would be a call to clk_set_parent(), but it's far less > > used, and it doesn't look like there's any obvious user for that clock. > > > > So, the set_parent hook is effectively unused, possibly because of an > > oversight. However, it could also be an explicit decision by the > > original author to avoid any reparenting but through an explicit call to > > clk_set_parent(). > > > > The driver does implement round_rate() though, which means that we can > > change the rate of the clock, but we will never get to change the > > parent. > > > > However, It's hard to tell whether it's been done on purpose or not. > > > > Since we'll start mandating a determine_rate() implementation, let's > > convert the round_rate() implementation to a determine_rate(), which > > will also make the current behavior explicit. And if it was an > > oversight, the clock behaviour can be adjusted later on. > > So it's partly on purpose, partly because I didn't know about > .determine_rate. > > There's nothing odd about having a lonely .set_parent callback; in my case > the clocks are parented from the device tree. > > Having the clocks driver trigger a parent change when requesting a rate > change sounds very dangerous, IMHO. My MMC controller can be parented to the > external 48 MHz oscillator, and if the card requests 50 MHz, it could switch > to one of the PLLs. That works as long as the PLLs don't change rate, but if > one is configured as driving the CPU clock, it becomes messy. > The thing is, the clocks driver has no way to know whether or not it is > "safe" to use a designated parent. > > For that reason, in practice, I never actually want to have a clock > re-parented - it's almost always a bad idea vs. sticking to the parent clock > configured in the DTS. Yeah, and this is totally fine. But we need to be explicit about it. The determine_rate implementation I did in all the patches is an exact equivalent to the round_rate one if there was one. We will never ask to change the parent. Given what you just said, I would suggest to set the CLK_SET_RATE_NO_REPARENT flag as well. > > > Signed-off-by: Maxime Ripard > > --- > > drivers/clk/ingenic/cgu.c | 15 --- > > 1 file changed, 8 insertions(+), 7 deletions(-) > > > > diff --git a/drivers/clk/ingenic/cgu.c b/drivers/clk/ingenic/cgu.c > > index 1f7ba30f5a1b..0c9c8344ad11 100644 > > --- a/drivers/clk/ingenic/cgu.c > > +++ b/drivers/clk/ingenic/cgu.c > > @@ -491,22 +491,23 @@ ingenic_clk_calc_div(struct clk_hw *hw, > > return div; > > } > > > > -static long > > -ingenic_clk_round_rate(struct clk_hw *hw, unsigned long req_rate, > > - unsigned long *parent_rate) > > +static int ingenic_clk_determine_rate(struct clk_hw *hw, > > + struct clk_rate_request *req) > > { > > struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw); > > const struct ingenic_cgu_clk_info *clk_info = > > to_clk_info(ingenic_clk); > > unsigned int div = 1; > > > > if (clk_info->type & CGU_CLK_DIV) > > - div = ingenic_clk_calc_div(hw, clk_info, *parent_rate, > > req_rate); > > + div = ingenic_clk_calc_div(hw, clk_info, req->best_parent_rate, > > + req->rate); > > Sorry but I'm not sure that this works. > > You replace the "parent_rate" with the "best_parent_rate", and that means > you only check the requested rate vs. the parent with the highest frequency, > and not vs. the actual parent that will be used. best_parent_rate is initialized to the current parent rate, not the parent with the highest frequency: https://elixir.bootlin.com/linux/v6.1-rc3/source/drivers/clk/clk.c#L1471 Maxime signature.asc Description: PGP signature
Re: Try to address the DMA-buf coherency problem
On Wed, Nov 2, 2022 at 5:21 AM Christian König wrote: > > Hi Lucas, > > Am 02.11.22 um 12:39 schrieb Lucas Stach: > > Hi Christian, > > > > going to reply in more detail when I have some more time, so just some > > quick thoughts for now. > > > > Am Mittwoch, dem 02.11.2022 um 12:18 +0100 schrieb Christian König: > >> Am 01.11.22 um 22:09 schrieb Nicolas Dufresne: > >>> [SNIP] > >> As far as I can see it you guys just allocate a buffer from a V4L2 > >> device, fill it with data and send it to Wayland for displaying. > >> > >> To be honest I'm really surprised that the Wayland guys hasn't pushed > >> back on this practice already. > >> > >> This only works because the Wayland as well as X display pipeline is > >> smart enough to insert an extra copy when it find that an imported > >> buffer can't be used as a framebuffer directly. > >> > > With bracketed access you could even make this case work, as the dGPU > > would be able to slurp a copy of the dma-buf into LMEM for scanout. > > Well, this copy is what we are trying to avoid here. The codec should > pump the data into LMEM in the first place. > For the dGPU VRAM case, shouldn't this be amdgpu re-importing it's own dmabuf, which more or less bypasses dma-buf to get back the backing GEM obj? BR, -R
Re: [PATCH v27 6/7] drm/mediatek: add drm ovl_adaptor sub driver for MT8195
On Fri, Nov 04, 2022 at 10:57:28AM +, Nancy Lin (林欣螢) wrote: > Dear Nicolas, > > Thanks for the review. > > On Thu, 2022-11-03 at 17:28 -0400, Nícolas F. R. A. Prado wrote: > > On Thu, Nov 03, 2022 at 11:26:09AM +0800, Nancy.Lin wrote: > > > Add drm ovl_adaptor sub driver. Bring up ovl_adaptor sub driver if > > > the component exists in the path. > > > > > > Signed-off-by: Nancy.Lin > > > Reviewed-by: AngeloGioacchino Del Regno < > > > angelogioacchino.delre...@collabora.com> > > > Reviewed-by: CK Hu > > > Tested-by: AngeloGioacchino Del Regno < > > > angelogioacchino.delre...@collabora.com> > > > Tested-by: Bo-Chen Chen > > > Tested-by: Nícolas F. R. A. Prado > > > Change-Id: I0501f3c80e78ec8279366cba9c137a2edd7a852e > > > --- > > > drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 61 - > > > drivers/gpu/drm/mediatek/mtk_drm_crtc.h | 2 +- > > > drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 129 -- > > > -- > > > drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h | 50 +++- > > > drivers/gpu/drm/mediatek/mtk_drm_drv.c | 78 ++-- > > > drivers/gpu/drm/mediatek/mtk_drm_drv.h | 12 +- > > > 6 files changed, 209 insertions(+), 123 deletions(-) > > > > > > diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c > > > b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c > > > index 30dcb65d8a5a..ce5617ad04cb 100644 > > > --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c > > > +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c > > > > [..] > > > int mtk_drm_crtc_create(struct drm_device *drm_dev, > > > - const enum mtk_ddp_comp_id *path, unsigned int > > > path_len, > > > + const unsigned int *path, unsigned int > > > path_len, > > > > Hi Nancy, > > > > why is 'enum mtk_ddp_comp_id' being changed to 'unsigned int' > > throughout this > > patch? Was this intentional? > > > > I saw that this change happened between v16 [1] and v17 [2], but I > > didn't see > > any reply or mention about this in the commit message or cover > > letter. > > > > Thanks, > > Nícolas > > > > [1] > > https://lore.kernel.org/all/20220318142009.2796-21-nancy@mediatek.com/ > > [2] > > https://lore.kernel.org/all/20220416020749.29010-20-nancy@mediatek.com/ > > > The change is for the review in [1] to expose each mod instead of ovl > adaptor to mtk_mutex. > Ovl adaptor is an application that combine these mod to achieve ovl > function, and it's not a real component in mtk_mmsys/mtk_mutex. > > For the above comment, I discussed the solution with MediaTek DRM > reviewer CK.Hu internally. > 1. remove the DDP_COMPONENT_OVL_ADAPTOR in enum mtk_ddp_comp_id{} (ref > [2]) > 2. add DRM driver component define "DDP_COMPONENT_DRM_OVL_ADAPTOR" in > mtk_drm_drv.h (ref[3]) > 3. replace mmsys compoent DDP_COMPONENT_OVL_ADAPTOR with DRM driver > compoent DDP_COMPONENT_DRM_OVL_ADAPTOR in drm mt8195_mtk_ddp_ext[] path > array. (ref[3] - mtk_drm_drv.c) > > static const unsigned int mt8195_mtk_ddp_ext[] = { > DDP_COMPONENT_DRM_OVL_ADAPTOR, > DDP_COMPONENT_MERGE5, > DDP_COMPONENT_DP_INTF1, > }; > Because the DDP_COMPONENT_DRM_OVL_ADAPTOR is not a real mmsys > component, change to use "unsigned int" instead of "enum > mtk_ddp_comp_id{}" Ah okay, that makes sense. Thank you for the clarification. Thanks, Nícolas > > > [1] > https://patchwork.kernel.org/project/linux-mediatek/patch/20220318142009.2796-10-nancy@mediatek.com/ > [2] > https://patchwork.kernel.org/project/linux-mediatek/patch/20220318142009.2796-5-nancy@mediatek.com/ > [3] > https://patchwork.kernel.org/project/linux-mediatek/patch/20221103032610.9217-7-nancy@mediatek.com/ > > Thanks, > Nancy >
Re: Try to address the DMA-buf coherency problem
Am 04.11.22 um 14:38 schrieb Nicolas Dufresne: Le vendredi 04 novembre 2022 à 10:03 +0100, Christian König a écrit : Am 03.11.22 um 23:16 schrieb Nicolas Dufresne: [SNIP] Was there APIs suggested to actually make it manageable by userland to allocate from the GPU? Yes, this what Linux Device Allocator idea is for. Is that API ready, no. Well, that stuff is absolutely ready: https://elixir.bootlin.com/linux/latest/source/drivers/dma-buf/heaps/system_heap.c#L175 What do you think I'm talking about all the time? I'm aware of DMA Heap, still have few gaps, but this unrelated to coherency (we can discuss offline, with Daniel S.). For DMABuf Heap, its used in many forks by vendors in production. There is an upstream proposal for GStreamer, but review comments were never addressed, in short, its stalled, and it waiting for a volunteer. It might also be based on very old implementation of DMABuf Heap, needs to be verified in depth for sure as the time have passed. https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1391 Well this is actually quite related to coherency. As general purpose framework it's mandatory for DMA Heaps to support the coherency callbacks. And as far as I can see they are indeed correctly implemented. So if you allocate from a DMA Heap it should be guaranteed that sharing with all devices work correctly, no matter if they write with the CPU or don't snoop the CPU cache. That's essentially what those heaps are good for. I just don't know how you should select between the contiguous and the system heap since I'm not deep enough in the userspace side of this. We should have come up with heaps earlier and don't implement so many different system memory allocators in the drivers in the first place. DMA-buf has a lengthy section about CPU access to buffers and clearly documents how all of that is supposed to work: https://elixir.bootlin.com/linux/latest/source/drivers/dma-buf/dma-buf.c#L1160 This includes braketing of CPU access with dma_buf_begin_cpu_access() and dma_buf_end_cpu_access(), as well as transaction management between devices and the CPU and even implicit synchronization. This specification is then implemented by the different drivers including V4L2: https://elixir.bootlin.com/linux/latest/source/drivers/media/common/videobuf2/videobuf2-dma-sg.c#L473 As well as the different DRM drivers: https://elixir.bootlin.com/linux/latest/source/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c#L117 https://elixir.bootlin.com/linux/latest/source/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c#L234 I know, I've implement the userspace bracketing for this in GStreamer [1] before DMAbuf Heap was merged and was one of the reporter for the missing bracketing in VB2. Was tested against i915 driver. Note, this is just a fallback, the performance is terrible, memory exported by (at least my old i915 HW) is not cacheable on CPU. Though, between corrupted image and bad performance or just bad performance, we decided that it was better to have the second. When the DMABuf is backed by CPU cacheable memory, peformance is great and CPU fallback works. Work is in progress to better handle these two cases generically. For now, sometimes the app need to get involved, but this is only happens on embedded/controlled kind of use cases. What matters is that application that needs this can do it. [1] https://gitlab.freedesktop.org/gstreamer/gstreamer/-/blob/main/subprojects/gst-plugins-base/gst-libs/gst/allocators/gstdmabuf.c Yeah, I've heard complains about that before with people asking if we couldn't map buffers exporter by the GPU as cacheable and then flush it on demand. For i915 that's more or less possible because it just uses stolen system memory, but pretty much any other dGPU uses local memory and mapping a PCIe BAR cacheable is really a no-go. This design was then used by us with various media players on different customer projects, including QNAP https://www.qnap.com/en/product/ts-877 as well as the newest Tesla https://www.amd.com/en/products/embedded-automotive-solutions I won't go into the details here, but we are using exactly the approach I've outlined to let userspace control the DMA between the different device in question. I'm one of the main designers of that and our multimedia and mesa team has up-streamed quite a number of changes for this project. I'm not that well into different ARM based solutions because we are just recently getting results that this starts to work with AMD GPUs, but I'm pretty sure that the design should be able to handle that as well. So we have clearly prove that this design works, even with special requirements which are way more complex than what we are discussing here. We had cases where we used GStreamer to feed DMA-buf handles into multiple devices with different format requirements and that seems to work fine. Sounds like you have a love/hate relationship with GStreamer. Glad the framework is working for you too. The
Re: [PATCH] staging: fbtft: Use ARRAY_SIZE() to get argument count
On Fri, Nov 04, 2022 at 05:31:24PM +0530, Deepak R Varma wrote: > On Mon, Oct 31, 2022 at 01:05:32PM +0100, Julia Lawall wrote: > > > > > > I took a look, but it's pretty complex. You could take the code and > > reorganize it so that it is more readable, and then take the definition of > > the ARRAY_SIZE macro, to better see what is going on. > > > > julia > > > > Hello Greg, Julia, > I was able to successfully build the fbtft object file for arm architecture as > well. I used gcc 6.5.0 and 9.5.0 tool chains. It was successful using both. I > have attached the build log from my machine for your reference. > > I am also looking at the .i file and rearrange the expanded macro to > understand > it. However, since it is built successfully, I am not sure if that is truly > the > problem area. > > Should I resend the patch and check if it still errors the kernel build bot? > Anything else I can try? Looks like the change I proposed is causing nesting inside the write_reg function due to additional set of { & } brackets for the __VA_ARGS__ symbol. Am I understanding it right? > > Thank you, > ./drv
Re: [PATCH v2 56/65] clk: ingenic: cgu: Switch to determine_rate
Hi Maxime, Le ven. 4 nov. 2022 à 14:18:13 +0100, Maxime Ripard a écrit : The Ingenic CGU clocks implements a mux with a set_parent hook, but doesn't provide a determine_rate implementation. This is a bit odd, since set_parent() is there to, as its name implies, change the parent of a clock. However, the most likely candidate to trigger that parent change is a call to clk_set_rate(), with determine_rate() figuring out which parent is the best suited for a given rate. The other trigger would be a call to clk_set_parent(), but it's far less used, and it doesn't look like there's any obvious user for that clock. So, the set_parent hook is effectively unused, possibly because of an oversight. However, it could also be an explicit decision by the original author to avoid any reparenting but through an explicit call to clk_set_parent(). The driver does implement round_rate() though, which means that we can change the rate of the clock, but we will never get to change the parent. However, It's hard to tell whether it's been done on purpose or not. Since we'll start mandating a determine_rate() implementation, let's convert the round_rate() implementation to a determine_rate(), which will also make the current behavior explicit. And if it was an oversight, the clock behaviour can be adjusted later on. So it's partly on purpose, partly because I didn't know about .determine_rate. There's nothing odd about having a lonely .set_parent callback; in my case the clocks are parented from the device tree. Having the clocks driver trigger a parent change when requesting a rate change sounds very dangerous, IMHO. My MMC controller can be parented to the external 48 MHz oscillator, and if the card requests 50 MHz, it could switch to one of the PLLs. That works as long as the PLLs don't change rate, but if one is configured as driving the CPU clock, it becomes messy. The thing is, the clocks driver has no way to know whether or not it is "safe" to use a designated parent. For that reason, in practice, I never actually want to have a clock re-parented - it's almost always a bad idea vs. sticking to the parent clock configured in the DTS. Signed-off-by: Maxime Ripard --- drivers/clk/ingenic/cgu.c | 15 --- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/clk/ingenic/cgu.c b/drivers/clk/ingenic/cgu.c index 1f7ba30f5a1b..0c9c8344ad11 100644 --- a/drivers/clk/ingenic/cgu.c +++ b/drivers/clk/ingenic/cgu.c @@ -491,22 +491,23 @@ ingenic_clk_calc_div(struct clk_hw *hw, return div; } -static long -ingenic_clk_round_rate(struct clk_hw *hw, unsigned long req_rate, - unsigned long *parent_rate) +static int ingenic_clk_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw); const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk); unsigned int div = 1; if (clk_info->type & CGU_CLK_DIV) - div = ingenic_clk_calc_div(hw, clk_info, *parent_rate, req_rate); + div = ingenic_clk_calc_div(hw, clk_info, req->best_parent_rate, + req->rate); Sorry but I'm not sure that this works. You replace the "parent_rate" with the "best_parent_rate", and that means you only check the requested rate vs. the parent with the highest frequency, and not vs. the actual parent that will be used. Cheers, -Paul else if (clk_info->type & CGU_CLK_FIXDIV) div = clk_info->fixdiv.div; else if (clk_hw_can_set_rate_parent(hw)) - *parent_rate = req_rate; + req->best_parent_rate = req->rate; - return DIV_ROUND_UP(*parent_rate, div); + req->rate = DIV_ROUND_UP(req->best_parent_rate, div); + return 0; } static inline int ingenic_clk_check_stable(struct ingenic_cgu *cgu, @@ -626,7 +627,7 @@ static const struct clk_ops ingenic_clk_ops = { .set_parent = ingenic_clk_set_parent, .recalc_rate = ingenic_clk_recalc_rate, - .round_rate = ingenic_clk_round_rate, + .determine_rate = ingenic_clk_determine_rate, .set_rate = ingenic_clk_set_rate, .enable = ingenic_clk_enable, -- b4 0.11.0-dev-99e3a
[PATCH v2 65/65] clk: Warn if we register a mux without determine_rate
The determine_rate hook allows to select the proper parent and its rate for a given clock configuration. On another hand, set_parent is there to change the parent of a mux. Some clocks provide a set_parent hook but don't implement determine_rate. In such a case, set_parent is pretty much useless since the clock framework will always assume the current parent is to be used, and we will thus never change it. This situation can be solved in two ways: - either we don't need to change the parent, and we thus shouldn't implement set_parent; - or we don't want to change the parent, in this case we should set CLK_SET_RATE_NO_REPARENT; - or we're missing a determine_rate implementation. The latter is probably just an oversight from the driver's author, and we should thus raise their awareness about the fact that the current state of the driver is confusing. It's not clear at this point how many drivers are affected though, so let's make it a warning instead of an error for now. Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Maxime Ripard --- drivers/clk/clk.c | 7 +++ 1 file changed, 7 insertions(+) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 495d7497cc43..9eb0343629cc 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -3701,6 +3701,13 @@ static int __clk_core_init(struct clk_core *core) goto out; } + if (core->ops->set_parent && !core->ops->determine_rate) { + pr_err("%s: %s must implement .set_parent & .determine_rate\n", + __func__, core->name); + ret = -EINVAL; + goto out; + } + if (core->num_parents > 1 && !core->ops->get_parent) { pr_err("%s: %s must implement .get_parent as it has multi parents\n", __func__, core->name); -- b4 0.11.0-dev-99e3a
[PATCH v2 64/65] ASoC: tlv320aic32x4: div: Switch to determine_rate
The tlv320aic32x4 divider clocks implements a mux with a set_parent hook, but doesn't provide a determine_rate implementation. This is a bit odd, since set_parent() is there to, as its name implies, change the parent of a clock. However, the most likely candidate to trigger that parent change is a call to clk_set_rate(), with determine_rate() figuring out which parent is the best suited for a given rate. The other trigger would be a call to clk_set_parent(), but it's far less used, and it doesn't look like there's any obvious user for that clock. So, the set_parent hook is effectively unused, possibly because of an oversight. However, it could also be an explicit decision by the original author to avoid any reparenting but through an explicit call to clk_set_parent(). The driver does implement round_rate() though, which means that we can change the rate of the clock, but we will never get to change the parent. However, It's hard to tell whether it's been done on purpose or not. Since we'll start mandating a determine_rate() implementation, let's convert the round_rate() implementation to a determine_rate(), which will also make the current behavior explicit. And if it was an oversight, the clock behaviour can be adjusted later on. Signed-off-by: Maxime Ripard --- sound/soc/codecs/tlv320aic32x4-clk.c | 13 +++-- 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/tlv320aic32x4-clk.c b/sound/soc/codecs/tlv320aic32x4-clk.c index d8b8ea3eaa12..707c9951fac0 100644 --- a/sound/soc/codecs/tlv320aic32x4-clk.c +++ b/sound/soc/codecs/tlv320aic32x4-clk.c @@ -333,16 +333,17 @@ static int clk_aic32x4_div_set_rate(struct clk_hw *hw, unsigned long rate, AIC32X4_DIV_MASK, divisor); } -static long clk_aic32x4_div_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) +static int clk_aic32x4_div_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { unsigned long divisor; - divisor = DIV_ROUND_UP(*parent_rate, rate); + divisor = DIV_ROUND_UP(req->best_parent_rate, req->rate); if (divisor > 128) return -EINVAL; - return DIV_ROUND_UP(*parent_rate, divisor); + req->rate = DIV_ROUND_UP(req->best_parent_rate, divisor); + return 0; } static unsigned long clk_aic32x4_div_recalc_rate(struct clk_hw *hw, @@ -361,7 +362,7 @@ static const struct clk_ops aic32x4_div_ops = { .prepare = clk_aic32x4_div_prepare, .unprepare = clk_aic32x4_div_unprepare, .set_rate = clk_aic32x4_div_set_rate, - .round_rate = clk_aic32x4_div_round_rate, + .determine_rate = clk_aic32x4_div_determine_rate, .recalc_rate = clk_aic32x4_div_recalc_rate, }; @@ -389,7 +390,7 @@ static const struct clk_ops aic32x4_bdiv_ops = { .set_parent = clk_aic32x4_bdiv_set_parent, .get_parent = clk_aic32x4_bdiv_get_parent, .set_rate = clk_aic32x4_div_set_rate, - .round_rate = clk_aic32x4_div_round_rate, + .determine_rate = clk_aic32x4_div_determine_rate, .recalc_rate = clk_aic32x4_div_recalc_rate, }; -- b4 0.11.0-dev-99e3a
[PATCH v2 63/65] ASoC: tlv320aic32x4: pll: Switch to determine_rate
The tlv320aic32x4 PLL clocks implements a mux with a set_parent hook, but doesn't provide a determine_rate implementation. This is a bit odd, since set_parent() is there to, as its name implies, change the parent of a clock. However, the most likely candidate to trigger that parent change is a call to clk_set_rate(), with determine_rate() figuring out which parent is the best suited for a given rate. The other trigger would be a call to clk_set_parent(), but it's far less used, and it doesn't look like there's any obvious user for that clock. So, the set_parent hook is effectively unused, possibly because of an oversight. However, it could also be an explicit decision by the original author to avoid any reparenting but through an explicit call to clk_set_parent(). The driver does implement round_rate() though, which means that we can change the rate of the clock, but we will never get to change the parent. However, It's hard to tell whether it's been done on purpose or not. Since we'll start mandating a determine_rate() implementation, let's convert the round_rate() implementation to a determine_rate(), which will also make the current behavior explicit. And if it was an oversight, the clock behaviour can be adjusted later on. Signed-off-by: Maxime Ripard --- sound/soc/codecs/tlv320aic32x4-clk.c | 19 --- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/sound/soc/codecs/tlv320aic32x4-clk.c b/sound/soc/codecs/tlv320aic32x4-clk.c index 65b72373cb95..d8b8ea3eaa12 100644 --- a/sound/soc/codecs/tlv320aic32x4-clk.c +++ b/sound/soc/codecs/tlv320aic32x4-clk.c @@ -205,18 +205,23 @@ static unsigned long clk_aic32x4_pll_recalc_rate(struct clk_hw *hw, return clk_aic32x4_pll_calc_rate(&settings, parent_rate); } -static long clk_aic32x4_pll_round_rate(struct clk_hw *hw, - unsigned long rate, - unsigned long *parent_rate) +static int clk_aic32x4_pll_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { struct clk_aic32x4_pll_muldiv settings; + unsigned long rate; int ret; - ret = clk_aic32x4_pll_calc_muldiv(&settings, rate, *parent_rate); + ret = clk_aic32x4_pll_calc_muldiv(&settings, req->rate, req->best_parent_rate); if (ret < 0) - return 0; + return -EINVAL; - return clk_aic32x4_pll_calc_rate(&settings, *parent_rate); + rate = clk_aic32x4_pll_calc_rate(&settings, req->best_parent_rate); + if (rate < 0) + return rate; + + req->rate = rate; + return 0; } static int clk_aic32x4_pll_set_rate(struct clk_hw *hw, @@ -267,7 +272,7 @@ static const struct clk_ops aic32x4_pll_ops = { .unprepare = clk_aic32x4_pll_unprepare, .is_prepared = clk_aic32x4_pll_is_prepared, .recalc_rate = clk_aic32x4_pll_recalc_rate, - .round_rate = clk_aic32x4_pll_round_rate, + .determine_rate = clk_aic32x4_pll_determine_rate, .set_rate = clk_aic32x4_pll_set_rate, .set_parent = clk_aic32x4_pll_set_parent, .get_parent = clk_aic32x4_pll_get_parent, -- b4 0.11.0-dev-99e3a
Re: [PATCH v1 5/5] arm64: dts: qcom: sm8450-hdk: Enable HDMI Display
On 04/11/2022 09:13, Dmitry Baryshkov wrote: > From: Vinod Koul > > Add the HDMI display nodes and link it to DSI. Also enable missing dispcc > nodes > > Signed-off-by: Vinod Koul > Signed-off-by: Dmitry Baryshkov Thank you for your patch. There is something to discuss/improve. > +&dispcc { > + status = "okay"; > +}; > + > &dsi0 { > status = "okay"; > vdda-supply = <&vreg_l6b_1p2>; > + > + ports { > + port@1 { > + endpoint { > + remote-endpoint = <<9611_a>; > + data-lanes = <0 1 2 3>; > + }; > + }; > + }; > + Drop blank line. Reviewed-by: Krzysztof Kozlowski Best regards, Krzysztof
[PATCH v3 1/7] vfio/ccw: create a parent struct
Move the stuff associated with the mdev parent (and thus the subchannel struct) into its own struct, and leave the rest in the existing private structure. The subchannel will point to the parent, and the parent will point to the private, for the areas where one or both are needed. Further separation of these structs will follow. Signed-off-by: Eric Farman Reviewed-by: Matthew Rosato --- drivers/s390/cio/vfio_ccw_drv.c | 98 +++-- drivers/s390/cio/vfio_ccw_ops.c | 8 ++- drivers/s390/cio/vfio_ccw_private.h | 20 -- 3 files changed, 101 insertions(+), 25 deletions(-) diff --git a/drivers/s390/cio/vfio_ccw_drv.c b/drivers/s390/cio/vfio_ccw_drv.c index 7f5402fe857a..444b32047397 100644 --- a/drivers/s390/cio/vfio_ccw_drv.c +++ b/drivers/s390/cio/vfio_ccw_drv.c @@ -36,10 +36,19 @@ debug_info_t *vfio_ccw_debug_trace_id; */ int vfio_ccw_sch_quiesce(struct subchannel *sch) { - struct vfio_ccw_private *private = dev_get_drvdata(&sch->dev); + struct vfio_ccw_parent *parent = dev_get_drvdata(&sch->dev); + struct vfio_ccw_private *private = dev_get_drvdata(&parent->dev); DECLARE_COMPLETION_ONSTACK(completion); int iretry, ret = 0; + /* +* Probably an impossible situation, after being called through +* FSM callbacks. But in the event it did, register a warning +* and return as if things were fine. +*/ + if (WARN_ON(!private)) + return 0; + iretry = 255; do { @@ -121,7 +130,23 @@ static void vfio_ccw_crw_todo(struct work_struct *work) */ static void vfio_ccw_sch_irq(struct subchannel *sch) { - struct vfio_ccw_private *private = dev_get_drvdata(&sch->dev); + struct vfio_ccw_parent *parent = dev_get_drvdata(&sch->dev); + struct vfio_ccw_private *private = dev_get_drvdata(&parent->dev); + + /* +* The subchannel should still be disabled at this point, +* so an interrupt would be quite surprising. As with an +* interrupt while the FSM is closed, let's attempt to +* disable the subchannel again. +*/ + if (!private) { + VFIO_CCW_MSG_EVENT(2, "sch %x.%x.%04x: unexpected interrupt\n", + sch->schid.cssid, sch->schid.ssid, + sch->schid.sch_no); + + cio_disable_subchannel(sch); + return; + } inc_irq_stat(IRQIO_CIO); vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_INTERRUPT); @@ -201,10 +226,19 @@ static void vfio_ccw_free_private(struct vfio_ccw_private *private) mutex_destroy(&private->io_mutex); kfree(private); } + +static void vfio_ccw_free_parent(struct device *dev) +{ + struct vfio_ccw_parent *parent = container_of(dev, struct vfio_ccw_parent, dev); + + kfree(parent); +} + static int vfio_ccw_sch_probe(struct subchannel *sch) { struct pmcw *pmcw = &sch->schib.pmcw; struct vfio_ccw_private *private; + struct vfio_ccw_parent *parent; int ret = -ENOMEM; if (pmcw->qf) { @@ -213,38 +247,58 @@ static int vfio_ccw_sch_probe(struct subchannel *sch) return -ENODEV; } + parent = kzalloc(sizeof(*parent), GFP_KERNEL); + if (!parent) + return -ENOMEM; + + dev_set_name(&parent->dev, "parent"); + parent->dev.parent = &sch->dev; + parent->dev.release = &vfio_ccw_free_parent; + ret = device_register(&parent->dev); + if (ret) + goto out_free; + private = vfio_ccw_alloc_private(sch); - if (IS_ERR(private)) + if (IS_ERR(private)) { + device_unregister(&parent->dev); return PTR_ERR(private); + } - dev_set_drvdata(&sch->dev, private); + dev_set_drvdata(&sch->dev, parent); + dev_set_drvdata(&parent->dev, private); - private->mdev_type.sysfs_name = "io"; - private->mdev_type.pretty_name = "I/O subchannel (Non-QDIO)"; - private->mdev_types[0] = &private->mdev_type; - ret = mdev_register_parent(&private->parent, &sch->dev, + parent->mdev_type.sysfs_name = "io"; + parent->mdev_type.pretty_name = "I/O subchannel (Non-QDIO)"; + parent->mdev_types[0] = &parent->mdev_type; + ret = mdev_register_parent(&parent->parent, &sch->dev, &vfio_ccw_mdev_driver, - private->mdev_types, 1); + parent->mdev_types, 1); if (ret) - goto out_free; + goto out_unreg; VFIO_CCW_MSG_EVENT(4, "bound to subchannel %x.%x.%04x\n", sch->schid.cssid, sch->schid.ssid, sch->schid.sch_no); return 0; +out_unreg: + device_unregister(&parent->dev); out_free: + dev_set_drvdata(&parent->dev, NULL); dev_set_drvdata(&sch->dev,
[PATCH v3 7/7] vfio: Remove vfio_free_device
With the "mess" sorted out, we should be able to inline the vfio_free_device call introduced by commit cb9ff3f3b84c ("vfio: Add helpers for unifying vfio_device life cycle") and remove them from driver release callbacks. Signed-off-by: Eric Farman Reviewed-by: Jason Gunthorpe Reviewed-by: Kevin Tian Reviewed-by: Cornelia Huck Reviewed-by: Tony Krowiak # vfio-ap part Acked-by: Alex Williamson Reviewed-by: Matthew Rosato --- drivers/gpu/drm/i915/gvt/kvmgt.c | 1 - drivers/s390/cio/vfio_ccw_ops.c | 2 -- drivers/s390/crypto/vfio_ap_ops.c | 6 -- drivers/vfio/fsl-mc/vfio_fsl_mc.c | 1 - drivers/vfio/pci/vfio_pci_core.c | 1 - drivers/vfio/platform/vfio_amba.c | 1 - drivers/vfio/platform/vfio_platform.c | 1 - drivers/vfio/vfio_main.c | 22 -- include/linux/vfio.h | 1 - samples/vfio-mdev/mbochs.c| 1 - samples/vfio-mdev/mdpy.c | 1 - samples/vfio-mdev/mtty.c | 1 - 12 files changed, 4 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c index 7a45e5360caf..eee6805e67de 100644 --- a/drivers/gpu/drm/i915/gvt/kvmgt.c +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c @@ -1461,7 +1461,6 @@ static void intel_vgpu_release_dev(struct vfio_device *vfio_dev) struct intel_vgpu *vgpu = vfio_dev_to_vgpu(vfio_dev); intel_gvt_destroy_vgpu(vgpu); - vfio_free_device(vfio_dev); } static const struct vfio_device_ops intel_vgpu_dev_ops = { diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_ops.c index 1155f8bcedd9..598a3814d428 100644 --- a/drivers/s390/cio/vfio_ccw_ops.c +++ b/drivers/s390/cio/vfio_ccw_ops.c @@ -143,8 +143,6 @@ static void vfio_ccw_mdev_release_dev(struct vfio_device *vdev) kmem_cache_free(vfio_ccw_io_region, private->io_region); kfree(private->cp.guest_cp); mutex_destroy(&private->io_mutex); - - vfio_free_device(vdev); } static void vfio_ccw_mdev_remove(struct mdev_device *mdev) diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c index 0b4cc8c597ae..f108c0f14712 100644 --- a/drivers/s390/crypto/vfio_ap_ops.c +++ b/drivers/s390/crypto/vfio_ap_ops.c @@ -765,11 +765,6 @@ static void vfio_ap_mdev_unlink_fr_queues(struct ap_matrix_mdev *matrix_mdev) } } -static void vfio_ap_mdev_release_dev(struct vfio_device *vdev) -{ - vfio_free_device(vdev); -} - static void vfio_ap_mdev_remove(struct mdev_device *mdev) { struct ap_matrix_mdev *matrix_mdev = dev_get_drvdata(&mdev->dev); @@ -1784,7 +1779,6 @@ static const struct attribute_group vfio_queue_attr_group = { static const struct vfio_device_ops vfio_ap_matrix_dev_ops = { .init = vfio_ap_mdev_init_dev, - .release = vfio_ap_mdev_release_dev, .open_device = vfio_ap_mdev_open_device, .close_device = vfio_ap_mdev_close_device, .ioctl = vfio_ap_mdev_ioctl, diff --git a/drivers/vfio/fsl-mc/vfio_fsl_mc.c b/drivers/vfio/fsl-mc/vfio_fsl_mc.c index b16874e913e4..7b8889f55007 100644 --- a/drivers/vfio/fsl-mc/vfio_fsl_mc.c +++ b/drivers/vfio/fsl-mc/vfio_fsl_mc.c @@ -568,7 +568,6 @@ static void vfio_fsl_mc_release_dev(struct vfio_device *core_vdev) vfio_fsl_uninit_device(vdev); mutex_destroy(&vdev->igate); - vfio_free_device(core_vdev); } static int vfio_fsl_mc_remove(struct fsl_mc_device *mc_dev) diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c index badc9d828cac..9be2d5be5d95 100644 --- a/drivers/vfio/pci/vfio_pci_core.c +++ b/drivers/vfio/pci/vfio_pci_core.c @@ -2109,7 +2109,6 @@ void vfio_pci_core_release_dev(struct vfio_device *core_vdev) mutex_destroy(&vdev->vma_lock); kfree(vdev->region); kfree(vdev->pm_save); - vfio_free_device(core_vdev); } EXPORT_SYMBOL_GPL(vfio_pci_core_release_dev); diff --git a/drivers/vfio/platform/vfio_amba.c b/drivers/vfio/platform/vfio_amba.c index eaea63e5294c..18faf2678b99 100644 --- a/drivers/vfio/platform/vfio_amba.c +++ b/drivers/vfio/platform/vfio_amba.c @@ -95,7 +95,6 @@ static void vfio_amba_release_dev(struct vfio_device *core_vdev) vfio_platform_release_common(vdev); kfree(vdev->name); - vfio_free_device(core_vdev); } static void vfio_amba_remove(struct amba_device *adev) diff --git a/drivers/vfio/platform/vfio_platform.c b/drivers/vfio/platform/vfio_platform.c index 82cedcebfd90..9910451dc341 100644 --- a/drivers/vfio/platform/vfio_platform.c +++ b/drivers/vfio/platform/vfio_platform.c @@ -83,7 +83,6 @@ static void vfio_platform_release_dev(struct vfio_device *core_vdev) container_of(core_vdev, struct vfio_platform_device, vdev); vfio_platform_release_common(vdev); - vfio_free_device(core_vdev); } static int vfio_platform_remove(struct platform_device *pdev) diff --git a/drivers/vfio/vfio_main.c b/driv
[PATCH v3 6/7] vfio/ccw: replace vfio_init_device with _alloc_
Now that we have a reasonable separation of structs that follow the subchannel and mdev lifecycles, there's no reason we can't call the official vfio_alloc_device routine for our private data, and behave like everyone else. Signed-off-by: Eric Farman Reviewed-by: Kevin Tian Acked-by: Alex Williamson Reviewed-by: Matthew Rosato --- drivers/s390/cio/vfio_ccw_drv.c | 18 -- drivers/s390/cio/vfio_ccw_ops.c | 28 ++-- drivers/s390/cio/vfio_ccw_private.h | 2 -- drivers/vfio/vfio_main.c| 10 +- include/linux/vfio.h| 2 -- 5 files changed, 23 insertions(+), 37 deletions(-) diff --git a/drivers/s390/cio/vfio_ccw_drv.c b/drivers/s390/cio/vfio_ccw_drv.c index 9fbd1b27a1ac..c2a65808605a 100644 --- a/drivers/s390/cio/vfio_ccw_drv.c +++ b/drivers/s390/cio/vfio_ccw_drv.c @@ -152,24 +152,6 @@ static void vfio_ccw_sch_irq(struct subchannel *sch) vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_INTERRUPT); } -void vfio_ccw_free_private(struct vfio_ccw_private *private) -{ - struct vfio_ccw_crw *crw, *temp; - - list_for_each_entry_safe(crw, temp, &private->crw, next) { - list_del(&crw->next); - kfree(crw); - } - - kmem_cache_free(vfio_ccw_crw_region, private->crw_region); - kmem_cache_free(vfio_ccw_schib_region, private->schib_region); - kmem_cache_free(vfio_ccw_cmd_region, private->cmd_region); - kmem_cache_free(vfio_ccw_io_region, private->io_region); - kfree(private->cp.guest_cp); - mutex_destroy(&private->io_mutex); - kfree(private); -} - static void vfio_ccw_free_parent(struct device *dev) { struct vfio_ccw_parent *parent = container_of(dev, struct vfio_ccw_parent, dev); diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_ops.c index 8a929a9cf3c6..1155f8bcedd9 100644 --- a/drivers/s390/cio/vfio_ccw_ops.c +++ b/drivers/s390/cio/vfio_ccw_ops.c @@ -102,15 +102,10 @@ static int vfio_ccw_mdev_probe(struct mdev_device *mdev) struct vfio_ccw_private *private; int ret; - private = kzalloc(sizeof(*private), GFP_KERNEL); - if (!private) - return -ENOMEM; - - ret = vfio_init_device(&private->vdev, &mdev->dev, &vfio_ccw_dev_ops); - if (ret) { - kfree(private); - return ret; - } + private = vfio_alloc_device(vfio_ccw_private, vdev, &mdev->dev, + &vfio_ccw_dev_ops); + if (IS_ERR(private)) + return PTR_ERR(private); dev_set_drvdata(&parent->dev, private); @@ -135,8 +130,21 @@ static void vfio_ccw_mdev_release_dev(struct vfio_device *vdev) { struct vfio_ccw_private *private = container_of(vdev, struct vfio_ccw_private, vdev); + struct vfio_ccw_crw *crw, *temp; + + list_for_each_entry_safe(crw, temp, &private->crw, next) { + list_del(&crw->next); + kfree(crw); + } + + kmem_cache_free(vfio_ccw_crw_region, private->crw_region); + kmem_cache_free(vfio_ccw_schib_region, private->schib_region); + kmem_cache_free(vfio_ccw_cmd_region, private->cmd_region); + kmem_cache_free(vfio_ccw_io_region, private->io_region); + kfree(private->cp.guest_cp); + mutex_destroy(&private->io_mutex); - vfio_ccw_free_private(private); + vfio_free_device(vdev); } static void vfio_ccw_mdev_remove(struct mdev_device *mdev) diff --git a/drivers/s390/cio/vfio_ccw_private.h b/drivers/s390/cio/vfio_ccw_private.h index 2278fd38d34e..b441ae6700fd 100644 --- a/drivers/s390/cio/vfio_ccw_private.h +++ b/drivers/s390/cio/vfio_ccw_private.h @@ -131,8 +131,6 @@ int vfio_ccw_sch_quiesce(struct subchannel *sch); void vfio_ccw_sch_io_todo(struct work_struct *work); void vfio_ccw_crw_todo(struct work_struct *work); -void vfio_ccw_free_private(struct vfio_ccw_private *private); - extern struct mdev_driver vfio_ccw_mdev_driver; /* diff --git a/drivers/vfio/vfio_main.c b/drivers/vfio/vfio_main.c index 2d168793d4e1..2901b8ad5be9 100644 --- a/drivers/vfio/vfio_main.c +++ b/drivers/vfio/vfio_main.c @@ -348,6 +348,9 @@ static void vfio_device_release(struct device *dev) device->ops->release(device); } +static int vfio_init_device(struct vfio_device *device, struct device *dev, + const struct vfio_device_ops *ops); + /* * Allocate and initialize vfio_device so it can be registered to vfio * core. @@ -386,11 +389,9 @@ EXPORT_SYMBOL_GPL(_vfio_alloc_device); /* * Initialize a vfio_device so it can be registered to vfio core. - * - * Only vfio-ccw driver should call this interface. */ -int vfio_init_device(struct vfio_device *device, struct device *dev, -const struct vfio_device_ops *ops) +static int vfio_init_device(struct vfio_device *device, struct device *dev, + const struct vfio_device_ops
[PATCH v3 2/7] vfio/ccw: remove private->sch
These places all rely on the ability to jump from a private struct back to the subchannel struct. Rather than keeping a copy in our back pocket, let's use the relationship provided by the vfio_device embedded within the private. Signed-off-by: Eric Farman Reviewed-by: Matthew Rosato --- drivers/s390/cio/vfio_ccw_chp.c | 5 +++-- drivers/s390/cio/vfio_ccw_drv.c | 3 +-- drivers/s390/cio/vfio_ccw_fsm.c | 27 --- drivers/s390/cio/vfio_ccw_ops.c | 12 ++-- drivers/s390/cio/vfio_ccw_private.h | 7 --- 5 files changed, 26 insertions(+), 28 deletions(-) diff --git a/drivers/s390/cio/vfio_ccw_chp.c b/drivers/s390/cio/vfio_ccw_chp.c index 13b26a1c7988..d3f3a611f95b 100644 --- a/drivers/s390/cio/vfio_ccw_chp.c +++ b/drivers/s390/cio/vfio_ccw_chp.c @@ -16,6 +16,7 @@ static ssize_t vfio_ccw_schib_region_read(struct vfio_ccw_private *private, char __user *buf, size_t count, loff_t *ppos) { + struct subchannel *sch = to_subchannel(private->vdev.dev->parent); unsigned int i = VFIO_CCW_OFFSET_TO_INDEX(*ppos) - VFIO_CCW_NUM_REGIONS; loff_t pos = *ppos & VFIO_CCW_OFFSET_MASK; struct ccw_schib_region *region; @@ -27,12 +28,12 @@ static ssize_t vfio_ccw_schib_region_read(struct vfio_ccw_private *private, mutex_lock(&private->io_mutex); region = private->region[i].data; - if (cio_update_schib(private->sch)) { + if (cio_update_schib(sch)) { ret = -ENODEV; goto out; } - memcpy(region, &private->sch->schib, sizeof(*region)); + memcpy(region, &sch->schib, sizeof(*region)); if (copy_to_user(buf, (void *)region + pos, count)) { ret = -EFAULT; diff --git a/drivers/s390/cio/vfio_ccw_drv.c b/drivers/s390/cio/vfio_ccw_drv.c index 444b32047397..2c680a556383 100644 --- a/drivers/s390/cio/vfio_ccw_drv.c +++ b/drivers/s390/cio/vfio_ccw_drv.c @@ -160,7 +160,6 @@ static struct vfio_ccw_private *vfio_ccw_alloc_private(struct subchannel *sch) if (!private) return ERR_PTR(-ENOMEM); - private->sch = sch; mutex_init(&private->io_mutex); private->state = VFIO_CCW_STATE_STANDBY; INIT_LIST_HEAD(&private->crw); @@ -395,7 +394,7 @@ static int vfio_ccw_chp_event(struct subchannel *sch, if (!private || !mask) return 0; - trace_vfio_ccw_chp_event(private->sch->schid, mask, event); + trace_vfio_ccw_chp_event(sch->schid, mask, event); VFIO_CCW_MSG_EVENT(2, "sch %x.%x.%04x: mask=0x%x event=%d\n", sch->schid.cssid, sch->schid.ssid, sch->schid.sch_no, diff --git a/drivers/s390/cio/vfio_ccw_fsm.c b/drivers/s390/cio/vfio_ccw_fsm.c index a59c758869f8..e67fad897af3 100644 --- a/drivers/s390/cio/vfio_ccw_fsm.c +++ b/drivers/s390/cio/vfio_ccw_fsm.c @@ -18,15 +18,13 @@ static int fsm_io_helper(struct vfio_ccw_private *private) { - struct subchannel *sch; + struct subchannel *sch = to_subchannel(private->vdev.dev->parent); union orb *orb; int ccode; __u8 lpm; unsigned long flags; int ret; - sch = private->sch; - spin_lock_irqsave(sch->lock, flags); orb = cp_get_orb(&private->cp, (u32)(addr_t)sch, sch->lpm); @@ -80,13 +78,11 @@ static int fsm_io_helper(struct vfio_ccw_private *private) static int fsm_do_halt(struct vfio_ccw_private *private) { - struct subchannel *sch; + struct subchannel *sch = to_subchannel(private->vdev.dev->parent); unsigned long flags; int ccode; int ret; - sch = private->sch; - spin_lock_irqsave(sch->lock, flags); VFIO_CCW_TRACE_EVENT(2, "haltIO"); @@ -121,13 +117,11 @@ static int fsm_do_halt(struct vfio_ccw_private *private) static int fsm_do_clear(struct vfio_ccw_private *private) { - struct subchannel *sch; + struct subchannel *sch = to_subchannel(private->vdev.dev->parent); unsigned long flags; int ccode; int ret; - sch = private->sch; - spin_lock_irqsave(sch->lock, flags); VFIO_CCW_TRACE_EVENT(2, "clearIO"); @@ -160,7 +154,7 @@ static int fsm_do_clear(struct vfio_ccw_private *private) static void fsm_notoper(struct vfio_ccw_private *private, enum vfio_ccw_event event) { - struct subchannel *sch = private->sch; + struct subchannel *sch = to_subchannel(private->vdev.dev->parent); VFIO_CCW_MSG_EVENT(2, "sch %x.%x.%04x: notoper event %x state %x\n", sch->schid.cssid, @@ -228,7 +222,7 @@ static void fsm_async_retry(struct vfio_ccw_private *private, static void fsm_disabled_irq(struct vfio_ccw_private *private, enum vfio_ccw_event event) { - struct subchannel *sch = private->sch; + str
[PATCH v3 5/7] vfio/ccw: remove release completion
There's enough separation between the parent and private structs now, that it is fine to remove the release completion hack. Signed-off-by: Eric Farman Reviewed-by: Kevin Tian Reviewed-by: Matthew Rosato --- drivers/s390/cio/vfio_ccw_ops.c | 14 +- drivers/s390/cio/vfio_ccw_private.h | 3 --- 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_ops.c index e45d4acb109b..8a929a9cf3c6 100644 --- a/drivers/s390/cio/vfio_ccw_ops.c +++ b/drivers/s390/cio/vfio_ccw_ops.c @@ -54,7 +54,6 @@ static int vfio_ccw_mdev_init_dev(struct vfio_device *vdev) INIT_LIST_HEAD(&private->crw); INIT_WORK(&private->io_work, vfio_ccw_sch_io_todo); INIT_WORK(&private->crw_work, vfio_ccw_crw_todo); - init_completion(&private->release_comp); private->cp.guest_cp = kcalloc(CCWCHAIN_LEN_MAX, sizeof(struct ccw1), GFP_KERNEL); @@ -137,7 +136,7 @@ static void vfio_ccw_mdev_release_dev(struct vfio_device *vdev) struct vfio_ccw_private *private = container_of(vdev, struct vfio_ccw_private, vdev); - complete(&private->release_comp); + vfio_ccw_free_private(private); } static void vfio_ccw_mdev_remove(struct mdev_device *mdev) @@ -155,17 +154,6 @@ static void vfio_ccw_mdev_remove(struct mdev_device *mdev) dev_set_drvdata(&parent->dev, NULL); vfio_put_device(&private->vdev); - /* -* Wait for all active references on mdev are released so it -* is safe to defer kfree() to a later point. -* -* TODO: the clean fix is to split parent/mdev info from ccw -* private structure so each can be managed in its own life -* cycle. -*/ - wait_for_completion(&private->release_comp); - - vfio_ccw_free_private(private); } static int vfio_ccw_mdev_open_device(struct vfio_device *vdev) diff --git a/drivers/s390/cio/vfio_ccw_private.h b/drivers/s390/cio/vfio_ccw_private.h index 747aba5f5272..2278fd38d34e 100644 --- a/drivers/s390/cio/vfio_ccw_private.h +++ b/drivers/s390/cio/vfio_ccw_private.h @@ -102,7 +102,6 @@ struct vfio_ccw_parent { * @req_trigger: eventfd ctx for signaling userspace to return device * @io_work: work for deferral process of I/O handling * @crw_work: work for deferral process of CRW handling - * @release_comp: synchronization helper for vfio device release */ struct vfio_ccw_private { struct vfio_device vdev; @@ -126,8 +125,6 @@ struct vfio_ccw_private { struct eventfd_ctx *req_trigger; struct work_struct io_work; struct work_struct crw_work; - - struct completion release_comp; } __aligned(8); int vfio_ccw_sch_quiesce(struct subchannel *sch); -- 2.34.1
[PATCH v3 4/7] vfio/ccw: move private to mdev lifecycle
Now that the mdev parent data is split out into its own struct, it is safe to move the remaining private data to follow the mdev probe/remove lifecycle. The mdev parent data will remain where it is, and follow the subchannel and the css driver interfaces. Signed-off-by: Eric Farman Reviewed-by: Matthew Rosato --- drivers/s390/cio/vfio_ccw_drv.c | 16 +--- drivers/s390/cio/vfio_ccw_ops.c | 26 +- drivers/s390/cio/vfio_ccw_private.h | 2 ++ 3 files changed, 16 insertions(+), 28 deletions(-) diff --git a/drivers/s390/cio/vfio_ccw_drv.c b/drivers/s390/cio/vfio_ccw_drv.c index fbc26338ceab..9fbd1b27a1ac 100644 --- a/drivers/s390/cio/vfio_ccw_drv.c +++ b/drivers/s390/cio/vfio_ccw_drv.c @@ -152,7 +152,7 @@ static void vfio_ccw_sch_irq(struct subchannel *sch) vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_INTERRUPT); } -static void vfio_ccw_free_private(struct vfio_ccw_private *private) +void vfio_ccw_free_private(struct vfio_ccw_private *private) { struct vfio_ccw_crw *crw, *temp; @@ -180,7 +180,6 @@ static void vfio_ccw_free_parent(struct device *dev) static int vfio_ccw_sch_probe(struct subchannel *sch) { struct pmcw *pmcw = &sch->schib.pmcw; - struct vfio_ccw_private *private; struct vfio_ccw_parent *parent; int ret = -ENOMEM; @@ -201,14 +200,7 @@ static int vfio_ccw_sch_probe(struct subchannel *sch) if (ret) goto out_free; - private = kzalloc(sizeof(*private), GFP_KERNEL); - if (!private) { - device_unregister(&parent->dev); - return -ENOMEM; - } - dev_set_drvdata(&sch->dev, parent); - dev_set_drvdata(&parent->dev, private); parent->mdev_type.sysfs_name = "io"; parent->mdev_type.pretty_name = "I/O subchannel (Non-QDIO)"; @@ -227,25 +219,19 @@ static int vfio_ccw_sch_probe(struct subchannel *sch) out_unreg: device_unregister(&parent->dev); out_free: - dev_set_drvdata(&parent->dev, NULL); dev_set_drvdata(&sch->dev, NULL); - if (private) - vfio_ccw_free_private(private); return ret; } static void vfio_ccw_sch_remove(struct subchannel *sch) { struct vfio_ccw_parent *parent = dev_get_drvdata(&sch->dev); - struct vfio_ccw_private *private = dev_get_drvdata(&parent->dev); mdev_unregister_parent(&parent->parent); device_unregister(&parent->dev); dev_set_drvdata(&sch->dev, NULL); - vfio_ccw_free_private(private); - VFIO_CCW_MSG_EVENT(4, "unbound from subchannel %x.%x.%04x\n", sch->schid.cssid, sch->schid.ssid, sch->schid.sch_no); diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_ops.c index eb0b8cc210bb..e45d4acb109b 100644 --- a/drivers/s390/cio/vfio_ccw_ops.c +++ b/drivers/s390/cio/vfio_ccw_ops.c @@ -100,15 +100,20 @@ static int vfio_ccw_mdev_probe(struct mdev_device *mdev) { struct subchannel *sch = to_subchannel(mdev->dev.parent); struct vfio_ccw_parent *parent = dev_get_drvdata(&sch->dev); - struct vfio_ccw_private *private = dev_get_drvdata(&parent->dev); + struct vfio_ccw_private *private; int ret; - if (private->state == VFIO_CCW_STATE_NOT_OPER) - return -ENODEV; + private = kzalloc(sizeof(*private), GFP_KERNEL); + if (!private) + return -ENOMEM; ret = vfio_init_device(&private->vdev, &mdev->dev, &vfio_ccw_dev_ops); - if (ret) + if (ret) { + kfree(private); return ret; + } + + dev_set_drvdata(&parent->dev, private); VFIO_CCW_MSG_EVENT(2, "sch %x.%x.%04x: create\n", sch->schid.cssid, @@ -122,6 +127,7 @@ static int vfio_ccw_mdev_probe(struct mdev_device *mdev) return 0; err_put_vdev: + dev_set_drvdata(&parent->dev, NULL); vfio_put_device(&private->vdev); return ret; } @@ -131,15 +137,6 @@ static void vfio_ccw_mdev_release_dev(struct vfio_device *vdev) struct vfio_ccw_private *private = container_of(vdev, struct vfio_ccw_private, vdev); - /* -* We cannot free vfio_ccw_private here because it includes -* parent info which must be free'ed by css driver. -* -* Use a workaround by memset'ing the core device part and -* then notifying the remove path that all active references -* to this device have been released. -*/ - memset(vdev, 0, sizeof(*vdev)); complete(&private->release_comp); } @@ -156,6 +153,7 @@ static void vfio_ccw_mdev_remove(struct mdev_device *mdev) vfio_unregister_group_dev(&private->vdev); + dev_set_drvdata(&parent->dev, NULL); vfio_put_device(&private->vdev); /* * Wait for all active references on mdev are released so it @@ -166,6 +164,8 @@ static
[PATCH v3 0/7] vfio-ccw parent rework
Hi Alex, Here's the (last?) update to the vfio-ccw lifecycle changes that I've sent recently, and were previously discussed at various points [1][2]. Patches 1-5 rework the behavior of the vfio-ccw driver's private struct. In summary, the mdev pieces are split out of vfio_ccw_private and into a new vfio_ccw_parent struct that will continue to follow today's lifecycle. The remainder (bulk) of the private struct moves to follow the mdev probe/remove pair. There's opportunity for further separation of the things in the private struct, which would simplify some of the vfio-ccw code, but it got too hairy as I started that. Once vfio-ccw is no longer considered unique, those cleanups can happen at our leisure. Patch 6 removes the trickery where vfio-ccw uses vfio_init_device instead of vfio_alloc_device, and thus removes vfio_init_device from the outside world. Patch 7 removes vfio_free_device from vfio-ccw and the other drivers (hello, CC list!), letting it be handled by vfio_device_release directly. I believe this covers everything in this space; let me know if not! Thanks, Eric [1] https://lore.kernel.org/kvm/0-v3-57c1502c62fd+2190-ccw_mdev_...@nvidia.com/ [2] https://lore.kernel.org/kvm/20220602171948.2790690-1-far...@linux.ibm.com/ v2->v3: - [MR] Added r-b to remaining patches (Thank you!) - Patch 1: [gfx checkpatch] Whitespace [EF] Remove put_device(&parent->dev) [MR] Fix error exit when alloc of parent fails [MR] Check for !private on sch_probe error path - Patch 3: [EF] Fix error exit when alloc of private fails - Patch 6: [AW] Added ack (Thank you!) - Patch 7: [CH, AK] Added r-b (Thank you!) [AW] Added ack (Thank you!) v2: https://lore.kernel.org/kvm/20221102150152.2521475-1-far...@linux.ibm.com/ v1: https://lore.kernel.org/kvm/20221019162135.798901-1-far...@linux.ibm.com/ Eric Farman (7): vfio/ccw: create a parent struct vfio/ccw: remove private->sch vfio/ccw: move private initialization to callback vfio/ccw: move private to mdev lifecycle vfio/ccw: remove release completion vfio/ccw: replace vfio_init_device with _alloc_ vfio: Remove vfio_free_device drivers/gpu/drm/i915/gvt/kvmgt.c | 1 - drivers/s390/cio/vfio_ccw_chp.c | 5 +- drivers/s390/cio/vfio_ccw_drv.c | 173 +++--- drivers/s390/cio/vfio_ccw_fsm.c | 27 ++-- drivers/s390/cio/vfio_ccw_ops.c | 107 +++- drivers/s390/cio/vfio_ccw_private.h | 37 -- drivers/s390/crypto/vfio_ap_ops.c | 6 - drivers/vfio/fsl-mc/vfio_fsl_mc.c | 1 - drivers/vfio/pci/vfio_pci_core.c | 1 - drivers/vfio/platform/vfio_amba.c | 1 - drivers/vfio/platform/vfio_platform.c | 1 - drivers/vfio/vfio_main.c | 32 ++--- include/linux/vfio.h | 3 - samples/vfio-mdev/mbochs.c| 1 - samples/vfio-mdev/mdpy.c | 1 - samples/vfio-mdev/mtty.c | 1 - 16 files changed, 196 insertions(+), 202 deletions(-) -- 2.34.1
[PATCH v3 3/7] vfio/ccw: move private initialization to callback
There's already a device initialization callback that is used to initialize the release completion workaround that was introduced by commit ebb72b765fb49 ("vfio/ccw: Use the new device life cycle helpers"). Move the other elements of the vfio_ccw_private struct that require distinct initialization over to that routine. With that done, the vfio_ccw_alloc_private routine only does a kzalloc, so fold it inline. Signed-off-by: Eric Farman Reviewed-by: Matthew Rosato --- drivers/s390/cio/vfio_ccw_drv.c | 74 - drivers/s390/cio/vfio_ccw_ops.c | 43 + drivers/s390/cio/vfio_ccw_private.h | 7 ++- 3 files changed, 58 insertions(+), 66 deletions(-) diff --git a/drivers/s390/cio/vfio_ccw_drv.c b/drivers/s390/cio/vfio_ccw_drv.c index 2c680a556383..fbc26338ceab 100644 --- a/drivers/s390/cio/vfio_ccw_drv.c +++ b/drivers/s390/cio/vfio_ccw_drv.c @@ -23,10 +23,10 @@ #include "vfio_ccw_private.h" struct workqueue_struct *vfio_ccw_work_q; -static struct kmem_cache *vfio_ccw_io_region; -static struct kmem_cache *vfio_ccw_cmd_region; -static struct kmem_cache *vfio_ccw_schib_region; -static struct kmem_cache *vfio_ccw_crw_region; +struct kmem_cache *vfio_ccw_io_region; +struct kmem_cache *vfio_ccw_cmd_region; +struct kmem_cache *vfio_ccw_schib_region; +struct kmem_cache *vfio_ccw_crw_region; debug_info_t *vfio_ccw_debug_msg_id; debug_info_t *vfio_ccw_debug_trace_id; @@ -79,7 +79,7 @@ int vfio_ccw_sch_quiesce(struct subchannel *sch) return ret; } -static void vfio_ccw_sch_io_todo(struct work_struct *work) +void vfio_ccw_sch_io_todo(struct work_struct *work) { struct vfio_ccw_private *private; struct irb *irb; @@ -115,7 +115,7 @@ static void vfio_ccw_sch_io_todo(struct work_struct *work) eventfd_signal(private->io_trigger, 1); } -static void vfio_ccw_crw_todo(struct work_struct *work) +void vfio_ccw_crw_todo(struct work_struct *work) { struct vfio_ccw_private *private; @@ -152,62 +152,6 @@ static void vfio_ccw_sch_irq(struct subchannel *sch) vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_INTERRUPT); } -static struct vfio_ccw_private *vfio_ccw_alloc_private(struct subchannel *sch) -{ - struct vfio_ccw_private *private; - - private = kzalloc(sizeof(*private), GFP_KERNEL); - if (!private) - return ERR_PTR(-ENOMEM); - - mutex_init(&private->io_mutex); - private->state = VFIO_CCW_STATE_STANDBY; - INIT_LIST_HEAD(&private->crw); - INIT_WORK(&private->io_work, vfio_ccw_sch_io_todo); - INIT_WORK(&private->crw_work, vfio_ccw_crw_todo); - - private->cp.guest_cp = kcalloc(CCWCHAIN_LEN_MAX, sizeof(struct ccw1), - GFP_KERNEL); - if (!private->cp.guest_cp) - goto out_free_private; - - private->io_region = kmem_cache_zalloc(vfio_ccw_io_region, - GFP_KERNEL | GFP_DMA); - if (!private->io_region) - goto out_free_cp; - - private->cmd_region = kmem_cache_zalloc(vfio_ccw_cmd_region, - GFP_KERNEL | GFP_DMA); - if (!private->cmd_region) - goto out_free_io; - - private->schib_region = kmem_cache_zalloc(vfio_ccw_schib_region, - GFP_KERNEL | GFP_DMA); - - if (!private->schib_region) - goto out_free_cmd; - - private->crw_region = kmem_cache_zalloc(vfio_ccw_crw_region, - GFP_KERNEL | GFP_DMA); - - if (!private->crw_region) - goto out_free_schib; - return private; - -out_free_schib: - kmem_cache_free(vfio_ccw_schib_region, private->schib_region); -out_free_cmd: - kmem_cache_free(vfio_ccw_cmd_region, private->cmd_region); -out_free_io: - kmem_cache_free(vfio_ccw_io_region, private->io_region); -out_free_cp: - kfree(private->cp.guest_cp); -out_free_private: - mutex_destroy(&private->io_mutex); - kfree(private); - return ERR_PTR(-ENOMEM); -} - static void vfio_ccw_free_private(struct vfio_ccw_private *private) { struct vfio_ccw_crw *crw, *temp; @@ -257,10 +201,10 @@ static int vfio_ccw_sch_probe(struct subchannel *sch) if (ret) goto out_free; - private = vfio_ccw_alloc_private(sch); - if (IS_ERR(private)) { + private = kzalloc(sizeof(*private), GFP_KERNEL); + if (!private) { device_unregister(&parent->dev); - return PTR_ERR(private); + return -ENOMEM; } dev_set_drvdata(&sch->dev, parent); diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_ops.c index 79c50cb7dcb8..eb0b8cc210bb 100644 --- a/drivers/s390/cio/vfio_ccw_ops.c +++ b/drivers/s390/cio/vfio_ccw_ops.c @@ -49,8 +49,51 @@ static int vfio_ccw_mdev_init_dev(struct vfio_device *vdev)
Re: [PATCH v1 4/5] arm64: dts: qcom: sm8450-hdk: Add LT9611uxc HDMI bridge
On 04/11/2022 09:13, Dmitry Baryshkov wrote: > From: Vinod Koul > > Add the LT9611uxc DSI-HDMI bridge and supplies > > Signed-off-by: Vinod Koul > Signed-off-by: Dmitry Baryshkov > --- > arch/arm64/boot/dts/qcom/sm8450-hdk.dts | 61 + > 1 file changed, 61 insertions(+) > > diff --git a/arch/arm64/boot/dts/qcom/sm8450-hdk.dts > b/arch/arm64/boot/dts/qcom/sm8450-hdk.dts > index e1a4cf1ee51d..9522dd29a38a 100644 > --- a/arch/arm64/boot/dts/qcom/sm8450-hdk.dts > +++ b/arch/arm64/boot/dts/qcom/sm8450-hdk.dts > @@ -20,6 +20,28 @@ chosen { > stdout-path = "serial0:115200n8"; > }; > > + lt9611_1v2: lt9611-vdd12-regulator { Node name: drop lt9611 > + compatible = "regulator-fixed"; > + regulator-name = "LT9611_1V2"; > + > + vin-supply = <&vph_pwr>; > + regulator-min-microvolt = <120>; > + regulator-max-microvolt = <120>; > + gpio = <&tlmm 9 GPIO_ACTIVE_HIGH>; > + enable-active-high; > + }; > + > + lt9611_3v3: lt9611-3v3 { Node name: drop lt9611 and add "regulator suffix > + compatible = "regulator-fixed"; > + regulator-name = "LT9611_3V3"; > + > + vin-supply = <&vreg_bob>; > + gpio = <&tlmm 109 GPIO_ACTIVE_HIGH>; > + regulator-min-microvolt = <330>; > + regulator-max-microvolt = <330>; > + enable-active-high; > + }; > + > vph_pwr: vph-pwr-regulator { > compatible = "regulator-fixed"; > regulator-name = "vph_pwr"; > @@ -349,6 +371,27 @@ vreg_l7e_2p8: ldo7 { > }; > }; > > +&i2c9 { > + status = "okay"; > + clock-frequency = <40>; > + > + lt9611_codec: hdmi-bridge@2b { > + compatible = "lontium,lt9611uxc"; > + reg = <0x2b>; > + > + interrupts-extended = <&tlmm 44 IRQ_TYPE_EDGE_FALLING>; > + > + reset-gpios = <&tlmm 107 GPIO_ACTIVE_HIGH>; > + > + vdd-supply = <<9611_1v2>; > + vcc-supply = <<9611_3v3>; > + > + pinctrl-names = "default"; > + pinctrl-0 = <<9611_irq_pin <9611_rst_pin>; > + > + }; > +}; > + > &pcie0 { > status = "okay"; > max-link-speed = <2>; > @@ -394,8 +437,26 @@ &qupv3_id_0 { > status = "okay"; > }; > > +&qupv3_id_1 { > + status = "okay"; > +}; > + > &tlmm { > gpio-reserved-ranges = <28 4>, <36 4>; > + > + lt9611_irq_pin: lt9611-irq { -state Best regards, Krzysztof
Re: [PATCH v1 5/5] arm64: dts: qcom: sm8450-hdk: Enable HDMI Display
On 04/11/2022 14:13, Dmitry Baryshkov wrote: From: Vinod Koul Add the HDMI display nodes and link it to DSI. Also enable missing dispcc nodes Signed-off-by: Vinod Koul Signed-off-by: Dmitry Baryshkov --- arch/arm64/boot/dts/qcom/sm8450-hdk.dts | 45 + 1 file changed, 45 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm8450-hdk.dts b/arch/arm64/boot/dts/qcom/sm8450-hdk.dts index 9522dd29a38a..f37f226e9b11 100644 --- a/arch/arm64/boot/dts/qcom/sm8450-hdk.dts +++ b/arch/arm64/boot/dts/qcom/sm8450-hdk.dts @@ -20,6 +20,17 @@ chosen { stdout-path = "serial0:115200n8"; }; + hdmi-out { + compatible = "hdmi-connector"; + type = "a"; + + port { + hdmi_con: endpoint { + remote-endpoint = <<9611_out>; + }; + }; + }; + lt9611_1v2: lt9611-vdd12-regulator { compatible = "regulator-fixed"; regulator-name = "LT9611_1V2"; @@ -389,6 +400,26 @@ lt9611_codec: hdmi-bridge@2b { pinctrl-names = "default"; pinctrl-0 = <<9611_irq_pin <9611_rst_pin>; + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + lt9611_a: endpoint { + remote-endpoint = <&dsi0_out>; + }; + }; + + port@2 { + reg = <2>; + + lt9611_out: endpoint { + remote-endpoint = <&hdmi_con>; + }; + }; + }; }; }; @@ -512,9 +543,23 @@ &mdss_mdp { status = "okay"; }; +&dispcc { + status = "okay"; +}; Please sort this alphabetically (though I think it's gonna be ok after you fix it in 3/5). With that: Reviewed-by: Konrad Dybcio Konrad + &dsi0 { status = "okay"; vdda-supply = <&vreg_l6b_1p2>; + + ports { + port@1 { + endpoint { + remote-endpoint = <<9611_a>; + data-lanes = <0 1 2 3>; + }; + }; + }; + }; &dsi0_phy {
Re: [PATCH v1 4/5] arm64: dts: qcom: sm8450-hdk: Add LT9611uxc HDMI bridge
On 04/11/2022 14:13, Dmitry Baryshkov wrote: From: Vinod Koul Add the LT9611uxc DSI-HDMI bridge and supplies Signed-off-by: Vinod Koul Signed-off-by: Dmitry Baryshkov --- arch/arm64/boot/dts/qcom/sm8450-hdk.dts | 61 + 1 file changed, 61 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm8450-hdk.dts b/arch/arm64/boot/dts/qcom/sm8450-hdk.dts index e1a4cf1ee51d..9522dd29a38a 100644 --- a/arch/arm64/boot/dts/qcom/sm8450-hdk.dts +++ b/arch/arm64/boot/dts/qcom/sm8450-hdk.dts @@ -20,6 +20,28 @@ chosen { stdout-path = "serial0:115200n8"; }; + lt9611_1v2: lt9611-vdd12-regulator { + compatible = "regulator-fixed"; + regulator-name = "LT9611_1V2"; + + vin-supply = <&vph_pwr>; + regulator-min-microvolt = <120>; + regulator-max-microvolt = <120>; + gpio = <&tlmm 9 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + lt9611_3v3: lt9611-3v3 { The previous node has -regulator, this one doesn't, please keep it consistent. + compatible = "regulator-fixed"; + regulator-name = "LT9611_3V3"; + + vin-supply = <&vreg_bob>; + gpio = <&tlmm 109 GPIO_ACTIVE_HIGH>; + regulator-min-microvolt = <330>; + regulator-max-microvolt = <330>; + enable-active-high; + }; + vph_pwr: vph-pwr-regulator { compatible = "regulator-fixed"; regulator-name = "vph_pwr"; @@ -349,6 +371,27 @@ vreg_l7e_2p8: ldo7 { }; }; +&i2c9 { + status = "okay"; + clock-frequency = <40>; Status last, please. With these fixes: Reviewed-by: Konrad Dybcio Konrad + + lt9611_codec: hdmi-bridge@2b { + compatible = "lontium,lt9611uxc"; + reg = <0x2b>; + + interrupts-extended = <&tlmm 44 IRQ_TYPE_EDGE_FALLING>; + + reset-gpios = <&tlmm 107 GPIO_ACTIVE_HIGH>; + + vdd-supply = <<9611_1v2>; + vcc-supply = <<9611_3v3>; + + pinctrl-names = "default"; + pinctrl-0 = <<9611_irq_pin <9611_rst_pin>; + + }; +}; + &pcie0 { status = "okay"; max-link-speed = <2>; @@ -394,8 +437,26 @@ &qupv3_id_0 { status = "okay"; }; +&qupv3_id_1 { + status = "okay"; +}; + &tlmm { gpio-reserved-ranges = <28 4>, <36 4>; + + lt9611_irq_pin: lt9611-irq { + pins = "gpio44"; + function = "gpio"; + bias-disable; + }; + + lt9611_rst_pin: lt9611-rst-state { + pins = "gpio107"; + function = "normal"; + + output-high; + input-disable; + }; }; &uart7 {
Re: [PATCH v1 2/5] arm64: dts: qcom: sm8450: add display hardware devices
On 04/11/2022 09:13, Dmitry Baryshkov wrote: > Add devices tree nodes describing display hardware on SM8450: > - Display Clock Controller > - MDSS > - MDP > - two DSI controllers and DSI PHYs > > This does not provide support for DP controllers present on SM8450. > > Signed-off-by: Dmitry Baryshkov > --- > arch/arm64/boot/dts/qcom/sm8450.dtsi | 284 ++- > 1 file changed, 280 insertions(+), 4 deletions(-) > > diff --git a/arch/arm64/boot/dts/qcom/sm8450.dtsi > b/arch/arm64/boot/dts/qcom/sm8450.dtsi > index 250e6b883ca3..23f989dedfdb 100644 > --- a/arch/arm64/boot/dts/qcom/sm8450.dtsi > +++ b/arch/arm64/boot/dts/qcom/sm8450.dtsi > @@ -2401,6 +2401,282 @@ camcc: clock-controller@ade { > status = "disabled"; > }; > > + mdss: mdss@ae0 { > + compatible = "qcom,sm8450-mdss"; > + reg = <0 0x0ae0 0 0x1000>; > + reg-names = "mdss"; > + > + /* same path used twice */ > + interconnects = <&mmss_noc MASTER_MDP_DISP 0 &mc_virt > SLAVE_EBI1_DISP 0>, > + <&mmss_noc MASTER_MDP_DISP 0 &mc_virt > SLAVE_EBI1_DISP 0>; > + interconnect-names = "mdp0-mem", "mdp1-mem"; > + > + resets = <&dispcc DISP_CC_MDSS_CORE_BCR>; > + > + power-domains = <&dispcc MDSS_GDSC>; > + > + clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>, > + <&gcc GCC_DISP_HF_AXI_CLK>, > + <&gcc GCC_DISP_SF_AXI_CLK>, > + <&dispcc DISP_CC_MDSS_MDP_CLK>; > + clock-names = "iface", "bus", "nrt_bus", "core"; > + > + interrupts = ; > + interrupt-controller; > + #interrupt-cells = <1>; > + > + iommus = <&apps_smmu 0x2800 0x402>; > + > + status = "disabled"; Status as last property. > + > + #address-cells = <2>; > + #size-cells = <2>; > + ranges; > + > + mdss_mdp: mdp@ae01000 { Isn't this "display-controller" in the bindings and other cases? > + compatible = "qcom,sm8450-dpu"; > + reg = <0 0x0ae01000 0 0x8f000>, > + <0 0x0aeb 0 0x2008>; > + reg-names = "mdp", "vbif"; > + > + clocks = <&gcc GCC_DISP_HF_AXI_CLK>, > + <&gcc GCC_DISP_SF_AXI_CLK>, > + <&dispcc DISP_CC_MDSS_AHB_CLK>, > + <&dispcc DISP_CC_MDSS_MDP_LUT_CLK>, > + <&dispcc DISP_CC_MDSS_MDP_CLK>, > + <&dispcc DISP_CC_MDSS_VSYNC_CLK>; > + clock-names = "bus", > + "nrt_bus", > + "iface", > + "lut", > + "core", > + "vsync"; > + > + assigned-clocks = <&dispcc > DISP_CC_MDSS_VSYNC_CLK>; > + assigned-clock-rates = <1920>; > + > + operating-points-v2 = <&mdp_opp_table>; > + power-domains = <&rpmhpd SM8450_MMCX>; > + > + interrupt-parent = <&mdss>; > + interrupts = <0>; > + > + ports { > + #address-cells = <1>; > + #size-cells = <0>; > + > + port@0 { > + reg = <0>; > + dpu_intf1_out: endpoint { > + remote-endpoint = > <&dsi0_in>; > + }; > + }; > + > + port@1 { > + reg = <1>; > + dpu_intf2_out: endpoint { > + remote-endpoint = > <&dsi1_in>; > + }; > + }; > + > + }; > + > + mdp_opp_table: mdp-opp-table { > + compatible = "operating-points-v2"; > + > + opp-17200 { > + opp-hz = /bits/ 64 <17200>; > +
Re: [PATCH v1 3/5] arm64: dts: qcom: sm8450-hdk: enable display hardware
On 04/11/2022 14:13, Dmitry Baryshkov wrote: Enable MDSS/DPU/DSI0 on SM8450-HDK device. Note, there is no panel configuration (yet). Signed-off-by: Dmitry Baryshkov --- arch/arm64/boot/dts/qcom/sm8450-hdk.dts | 18 ++ 1 file changed, 18 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sm8450-hdk.dts b/arch/arm64/boot/dts/qcom/sm8450-hdk.dts index 38ccd44620d0..e1a4cf1ee51d 100644 --- a/arch/arm64/boot/dts/qcom/sm8450-hdk.dts +++ b/arch/arm64/boot/dts/qcom/sm8450-hdk.dts @@ -442,3 +442,21 @@ &usb_1_qmpphy { vdda-phy-supply = <&vreg_l6b_1p2>; vdda-pll-supply = <&vreg_l1b_0p91>; }; + +&mdss { + status = "okay"; +}; + +&mdss_mdp { + status = "okay"; +}; + +&dsi0 { + status = "okay"; + vdda-supply = <&vreg_l6b_1p2>; +}; + +&dsi0_phy { + status = "okay"; + vdds-supply = <&vreg_l5b_0p88>; +}; Sort the nodes alphabetically and place status last, please. Konrad
Re: [PATCH v1 2/5] arm64: dts: qcom: sm8450: add display hardware devices
On 04/11/2022 14:13, Dmitry Baryshkov wrote: Add devices tree nodes describing display hardware on SM8450: - Display Clock Controller - MDSS - MDP - two DSI controllers and DSI PHYs This does not provide support for DP controllers present on SM8450. Signed-off-by: Dmitry Baryshkov --- arch/arm64/boot/dts/qcom/sm8450.dtsi | 284 ++- 1 file changed, 280 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/sm8450.dtsi b/arch/arm64/boot/dts/qcom/sm8450.dtsi index 250e6b883ca3..23f989dedfdb 100644 --- a/arch/arm64/boot/dts/qcom/sm8450.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8450.dtsi @@ -2401,6 +2401,282 @@ camcc: clock-controller@ade { status = "disabled"; }; + mdss: mdss@ae0 { + compatible = "qcom,sm8450-mdss"; + reg = <0 0x0ae0 0 0x1000>; + reg-names = "mdss"; + + /* same path used twice */ + interconnects = <&mmss_noc MASTER_MDP_DISP 0 &mc_virt SLAVE_EBI1_DISP 0>, + <&mmss_noc MASTER_MDP_DISP 0 &mc_virt SLAVE_EBI1_DISP 0>; + interconnect-names = "mdp0-mem", "mdp1-mem"; + + resets = <&dispcc DISP_CC_MDSS_CORE_BCR>; + + power-domains = <&dispcc MDSS_GDSC>; + + clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>, +<&gcc GCC_DISP_HF_AXI_CLK>, +<&gcc GCC_DISP_SF_AXI_CLK>, +<&dispcc DISP_CC_MDSS_MDP_CLK>; + clock-names = "iface", "bus", "nrt_bus", "core"; + + interrupts = ; + interrupt-controller; + #interrupt-cells = <1>; + + iommus = <&apps_smmu 0x2800 0x402>; + + status = "disabled"; + + #address-cells = <2>; + #size-cells = <2>; + ranges; + + mdss_mdp: mdp@ae01000 { + compatible = "qcom,sm8450-dpu"; + reg = <0 0x0ae01000 0 0x8f000>, + <0 0x0aeb 0 0x2008>; + reg-names = "mdp", "vbif"; + + clocks = <&gcc GCC_DISP_HF_AXI_CLK>, + <&gcc GCC_DISP_SF_AXI_CLK>, + <&dispcc DISP_CC_MDSS_AHB_CLK>, + <&dispcc DISP_CC_MDSS_MDP_LUT_CLK>, + <&dispcc DISP_CC_MDSS_MDP_CLK>, + <&dispcc DISP_CC_MDSS_VSYNC_CLK>; + clock-names = "bus", + "nrt_bus", + "iface", + "lut", + "core", + "vsync"; + + assigned-clocks = <&dispcc DISP_CC_MDSS_VSYNC_CLK>; + assigned-clock-rates = <1920>; + + operating-points-v2 = <&mdp_opp_table>; + power-domains = <&rpmhpd SM8450_MMCX>; + + interrupt-parent = <&mdss>; + interrupts = <0>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + dpu_intf1_out: endpoint { + remote-endpoint = <&dsi0_in>; + }; + }; + + port@1 { + reg = <1>; + dpu_intf2_out: endpoint { + remote-endpoint = <&dsi1_in>; + }; + }; + + }; + + mdp_opp_table: mdp-opp-table { + compatible = "operating-points-v2"; + + opp-17200 { + opp-hz = /bits/ 64 <17200>; + required-opps = <&rpmhpd_opp_low_svs_d1>; + }; + + opp-2 { +
[PATCH v3 04/12] drm/mediatek: extract common functions from the mtk hdmi driver
Create a common "framework" that can be used to add support for different hdmi IPs within the mediatek range of products. Signed-off-by: Guillaume Ranquet --- drivers/gpu/drm/mediatek/Makefile | 3 +- drivers/gpu/drm/mediatek/mtk_hdmi.c| 620 ++--- drivers/gpu/drm/mediatek/mtk_hdmi.h| 16 + drivers/gpu/drm/mediatek/mtk_hdmi_common.c | 433 drivers/gpu/drm/mediatek/mtk_hdmi_common.h | 221 ++ 5 files changed, 704 insertions(+), 589 deletions(-) diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile index d4d193f60271..79bbaa58893e 100644 --- a/drivers/gpu/drm/mediatek/Makefile +++ b/drivers/gpu/drm/mediatek/Makefile @@ -22,7 +22,8 @@ obj-$(CONFIG_DRM_MEDIATEK) += mediatek-drm.o mediatek-drm-hdmi-objs := mtk_cec.o \ mtk_hdmi.o \ - mtk_hdmi_ddc.o + mtk_hdmi_common.o \ + mtk_hdmi_ddc.o \ obj-$(CONFIG_DRM_MEDIATEK_HDMI) += mediatek-drm-hdmi.o diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c index 9b02b30a193a..73bda2849196 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c @@ -31,187 +31,18 @@ #include #include "mtk_cec.h" -#include "mtk_hdmi.h" #include "mtk_hdmi_regs.h" +#include "mtk_hdmi_common.h" #define NCTS_BYTES 7 -enum mtk_hdmi_clk_id { - MTK_HDMI_CLK_HDMI_PIXEL, - MTK_HDMI_CLK_HDMI_PLL, - MTK_HDMI_CLK_AUD_BCLK, - MTK_HDMI_CLK_AUD_SPDIF, - MTK_HDMI_CLK_COUNT +const char * const mtk_hdmi_clk_names_v1[MTK_HDMIV1_CLK_COUNT] = { + [MTK_HDMIV1_CLK_HDMI_PIXEL] = "pixel", + [MTK_HDMIV1_CLK_HDMI_PLL] = "pll", + [MTK_HDMIV1_CLK_AUD_BCLK] = "bclk", + [MTK_HDMIV1_CLK_AUD_SPDIF] = "spdif", }; -enum hdmi_aud_input_type { - HDMI_AUD_INPUT_I2S = 0, - HDMI_AUD_INPUT_SPDIF, -}; - -enum hdmi_aud_i2s_fmt { - HDMI_I2S_MODE_RJT_24BIT = 0, - HDMI_I2S_MODE_RJT_16BIT, - HDMI_I2S_MODE_LJT_24BIT, - HDMI_I2S_MODE_LJT_16BIT, - HDMI_I2S_MODE_I2S_24BIT, - HDMI_I2S_MODE_I2S_16BIT -}; - -enum hdmi_aud_mclk { - HDMI_AUD_MCLK_128FS, - HDMI_AUD_MCLK_192FS, - HDMI_AUD_MCLK_256FS, - HDMI_AUD_MCLK_384FS, - HDMI_AUD_MCLK_512FS, - HDMI_AUD_MCLK_768FS, - HDMI_AUD_MCLK_1152FS, -}; - -enum hdmi_aud_channel_type { - HDMI_AUD_CHAN_TYPE_1_0 = 0, - HDMI_AUD_CHAN_TYPE_1_1, - HDMI_AUD_CHAN_TYPE_2_0, - HDMI_AUD_CHAN_TYPE_2_1, - HDMI_AUD_CHAN_TYPE_3_0, - HDMI_AUD_CHAN_TYPE_3_1, - HDMI_AUD_CHAN_TYPE_4_0, - HDMI_AUD_CHAN_TYPE_4_1, - HDMI_AUD_CHAN_TYPE_5_0, - HDMI_AUD_CHAN_TYPE_5_1, - HDMI_AUD_CHAN_TYPE_6_0, - HDMI_AUD_CHAN_TYPE_6_1, - HDMI_AUD_CHAN_TYPE_7_0, - HDMI_AUD_CHAN_TYPE_7_1, - HDMI_AUD_CHAN_TYPE_3_0_LRS, - HDMI_AUD_CHAN_TYPE_3_1_LRS, - HDMI_AUD_CHAN_TYPE_4_0_CLRS, - HDMI_AUD_CHAN_TYPE_4_1_CLRS, - HDMI_AUD_CHAN_TYPE_6_1_CS, - HDMI_AUD_CHAN_TYPE_6_1_CH, - HDMI_AUD_CHAN_TYPE_6_1_OH, - HDMI_AUD_CHAN_TYPE_6_1_CHR, - HDMI_AUD_CHAN_TYPE_7_1_LH_RH, - HDMI_AUD_CHAN_TYPE_7_1_LSR_RSR, - HDMI_AUD_CHAN_TYPE_7_1_LC_RC, - HDMI_AUD_CHAN_TYPE_7_1_LW_RW, - HDMI_AUD_CHAN_TYPE_7_1_LSD_RSD, - HDMI_AUD_CHAN_TYPE_7_1_LSS_RSS, - HDMI_AUD_CHAN_TYPE_7_1_LHS_RHS, - HDMI_AUD_CHAN_TYPE_7_1_CS_CH, - HDMI_AUD_CHAN_TYPE_7_1_CS_OH, - HDMI_AUD_CHAN_TYPE_7_1_CS_CHR, - HDMI_AUD_CHAN_TYPE_7_1_CH_OH, - HDMI_AUD_CHAN_TYPE_7_1_CH_CHR, - HDMI_AUD_CHAN_TYPE_7_1_OH_CHR, - HDMI_AUD_CHAN_TYPE_7_1_LSS_RSS_LSR_RSR, - HDMI_AUD_CHAN_TYPE_6_0_CS, - HDMI_AUD_CHAN_TYPE_6_0_CH, - HDMI_AUD_CHAN_TYPE_6_0_OH, - HDMI_AUD_CHAN_TYPE_6_0_CHR, - HDMI_AUD_CHAN_TYPE_7_0_LH_RH, - HDMI_AUD_CHAN_TYPE_7_0_LSR_RSR, - HDMI_AUD_CHAN_TYPE_7_0_LC_RC, - HDMI_AUD_CHAN_TYPE_7_0_LW_RW, - HDMI_AUD_CHAN_TYPE_7_0_LSD_RSD, - HDMI_AUD_CHAN_TYPE_7_0_LSS_RSS, - HDMI_AUD_CHAN_TYPE_7_0_LHS_RHS, - HDMI_AUD_CHAN_TYPE_7_0_CS_CH, - HDMI_AUD_CHAN_TYPE_7_0_CS_OH, - HDMI_AUD_CHAN_TYPE_7_0_CS_CHR, - HDMI_AUD_CHAN_TYPE_7_0_CH_OH, - HDMI_AUD_CHAN_TYPE_7_0_CH_CHR, - HDMI_AUD_CHAN_TYPE_7_0_OH_CHR, - HDMI_AUD_CHAN_TYPE_7_0_LSS_RSS_LSR_RSR, - HDMI_AUD_CHAN_TYPE_8_0_LH_RH_CS, - HDMI_AUD_CHAN_TYPE_UNKNOWN = 0xFF -}; - -enum hdmi_aud_channel_swap_type { - HDMI_AUD_SWAP_LR, - HDMI_AUD_SWAP_LFE_CC, - HDMI_AUD_SWAP_LSRS, - HDMI_AUD_SWAP_RLS_RRS, - HDMI_AUD_SWAP_LR_STATUS, -}; - -struct hdmi_audio_param { - enum hdmi_audio_coding_type aud_codec; - enum hdmi_audio_sample_size aud_sampe_size; - enum hdmi_aud_input_type aud_input_type; - enum hdmi_aud_i2s_fmt aud_i2s_fmt; - enum hdmi_aud_mclk aud_mclk; - e
[PATCH v3 11/12] dt-bindings: display: mediatek: dpi: Add compatible for MediaTek MT8195
Add dt-binding documentation of dpi for MediaTek MT8195 SoC. Acked-by: Krzysztof Kozlowski Signed-off-by: Guillaume Ranquet --- Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml index 5bb23e97cf33..2c7ecef54986 100644 --- a/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml +++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml @@ -24,6 +24,7 @@ properties: - mediatek,mt8183-dpi - mediatek,mt8186-dpi - mediatek,mt8192-dpi + - mediatek,mt8195-dpi - mediatek,mt8195-dp-intf reg: -- b4 0.11.0-dev
[PATCH v3 10/12] phy: mediatek: add support for phy-mtk-hdmi-mt8195
Add basic support for the mediatek hdmi phy on MT8195 SoC Signed-off-by: Guillaume Ranquet --- drivers/phy/mediatek/Makefile | 1 + drivers/phy/mediatek/phy-mtk-hdmi-mt8195.c | 543 + drivers/phy/mediatek/phy-mtk-hdmi-mt8195.h | 109 ++ drivers/phy/mediatek/phy-mtk-hdmi.c| 3 + drivers/phy/mediatek/phy-mtk-hdmi.h| 1 + 5 files changed, 657 insertions(+) diff --git a/drivers/phy/mediatek/Makefile b/drivers/phy/mediatek/Makefile index fb1f8edaffa7..c9a50395533e 100644 --- a/drivers/phy/mediatek/Makefile +++ b/drivers/phy/mediatek/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_PHY_MTK_XSPHY) += phy-mtk-xsphy.o phy-mtk-hdmi-drv-y := phy-mtk-hdmi.o phy-mtk-hdmi-drv-y += phy-mtk-hdmi-mt2701.o phy-mtk-hdmi-drv-y += phy-mtk-hdmi-mt8173.o +phy-mtk-hdmi-drv-y += phy-mtk-hdmi-mt8195.o obj-$(CONFIG_PHY_MTK_HDMI) += phy-mtk-hdmi-drv.o phy-mtk-mipi-dsi-drv-y := phy-mtk-mipi-dsi.o diff --git a/drivers/phy/mediatek/phy-mtk-hdmi-mt8195.c b/drivers/phy/mediatek/phy-mtk-hdmi-mt8195.c new file mode 100644 index ..48efd3936f29 --- /dev/null +++ b/drivers/phy/mediatek/phy-mtk-hdmi-mt8195.c @@ -0,0 +1,543 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2022 MediaTek Inc. + * Copyright (c) 2022 BayLibre, SAS + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "phy-mtk-io.h" +#include "phy-mtk-hdmi.h" +#include "phy-mtk-hdmi-mt8195.h" + +static void mtk_hdmi_ana_fifo_en(struct mtk_hdmi_phy *hdmi_phy) +{ + /* make data fifo writable for hdmi2.0 */ + mtk_phy_set_bits(hdmi_phy->regs + HDMI_ANA_CTL, REG_ANA_HDMI20_FIFO_EN); +} + +static void +mtk_mt8195_phy_tmds_high_bit_clk_ratio(struct mtk_hdmi_phy *hdmi_phy, + bool enable) +{ + void __iomem *regs = hdmi_phy->regs; + + mtk_hdmi_ana_fifo_en(hdmi_phy); + + /* HDMI 2.0 specification, 3.4Gbps <= TMDS Bit Rate <= 6G, +* clock bit ratio 1:40, under 3.4Gbps, clock bit ratio 1:10 +*/ + if (enable) + mtk_phy_update_field(regs + HDMI20_CLK_CFG, REG_TXC_DIV, REG_TXC_DIV); + else + mtk_phy_clear_bits(regs + HDMI20_CLK_CFG, REG_TXC_DIV); +} + +static void mtk_hdmi_pll_select_source(struct clk_hw *hw) +{ + struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw); + void __iomem *regs = hdmi_phy->regs; + + mtk_phy_clear_bits(regs + HDMI_CTL_3, REG_HDMITX_REF_XTAL_SEL); + mtk_phy_clear_bits(regs + HDMI_CTL_3, REG_HDMITX_REF_RESPLL_SEL); + + /* DA_HDMITX21_REF_CK for TXPLL input source */ + mtk_phy_clear_bits(regs + HDMI_1_CFG_10, RG_HDMITXPLL_REF_CK_SEL); +} + +static int mtk_hdmi_pll_performance_setting(struct clk_hw *hw) +{ + struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw); + void __iomem *regs = hdmi_phy->regs; + + /* BP2 */ + mtk_phy_set_bits(regs + HDMI_1_PLL_CFG_0, RG_HDMITXPLL_BP2); + + /* BC */ + mtk_phy_set_bits(regs + HDMI_1_PLL_CFG_2, RG_HDMITXPLL_BC); + + /* IC */ + mtk_phy_update_field(regs + HDMI_1_PLL_CFG_2, RG_HDMITXPLL_IC, 0x1); + + /* BR */ + mtk_phy_update_field(regs + HDMI_1_PLL_CFG_2, RG_HDMITXPLL_BR, 0x2); + + /* IR */ + mtk_phy_update_field(regs + HDMI_1_PLL_CFG_2, RG_HDMITXPLL_IR, 0x2); + + /* BP */ + mtk_phy_set_bits(regs + HDMI_1_PLL_CFG_2, RG_HDMITXPLL_BP); + + /* IBAND_FIX_EN, RESERVE[14] */ + mtk_phy_clear_bits(regs + HDMI_1_PLL_CFG_0, RG_HDMITXPLL_IBAND_FIX_EN); + mtk_phy_clear_bits(regs + HDMI_1_PLL_CFG_1, RG_HDMITXPLL_RESERVE_BIT14); + + /* HIKVCO */ + mtk_phy_clear_bits(regs + HDMI_1_PLL_CFG_2, RG_HDMITXPLL_HIKVCO); + + /* HREN */ + mtk_phy_update_field(regs + HDMI_1_PLL_CFG_0, RG_HDMITXPLL_HREN, 0x1); + + /* LVR_SEL */ + mtk_phy_update_field(regs + HDMI_1_PLL_CFG_0, RG_HDMITXPLL_LVR_SEL, 0x1); + + /* RG_HDMITXPLL_RESERVE[12:11] */ + mtk_phy_set_bits(regs + HDMI_1_PLL_CFG_1, RG_HDMITXPLL_RESERVE_BIT12_11); + + /* TCL_EN */ + mtk_phy_set_bits(regs + HDMI_1_PLL_CFG_0, RG_HDMITXPLL_TCL_EN); + + return 0; +} + +static int mtk_hdmi_pll_set_hw(struct clk_hw *hw, unsigned char prediv, + unsigned char fbkdiv_high, + unsigned long fbkdiv_low, + unsigned char fbkdiv_hs3, unsigned char posdiv1, + unsigned char posdiv2, unsigned char txprediv, + unsigned char txposdiv, + unsigned char digital_div) +{ + unsigned char txposdiv_value = 0; + unsigned char div3_ctrl_value = 0; + unsigned char posdiv_vallue = 0; + unsigned char div_ctrl_value = 0; + unsigned char reserve_3_2_value = 0; + uns
[PATCH v3 08/12] drm/mediatek: hdmi: v2: add audio support
Add HDMI audio support for v2 Signed-off-by: Guillaume Ranquet --- drivers/gpu/drm/mediatek/mtk_hdmi_common.c | 1 + drivers/gpu/drm/mediatek/mtk_hdmi_ddc_v2.c | 2 +- drivers/gpu/drm/mediatek/mtk_hdmi_v2.c | 213 + drivers/gpu/drm/mediatek/mtk_hdmi_v2.h | 2 + 4 files changed, 217 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi_common.c b/drivers/gpu/drm/mediatek/mtk_hdmi_common.c index e43c938a9aa5..1ea91f8bb6c7 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi_common.c +++ b/drivers/gpu/drm/mediatek/mtk_hdmi_common.c @@ -386,6 +386,7 @@ static const struct mtk_hdmi_conf mtk_hdmi_conf_v2 = { .mtk_hdmi_output_init = mtk_hdmi_output_init_v2, .mtk_hdmi_clk_disable = mtk_hdmi_clk_disable_v2, .mtk_hdmi_clk_enable = mtk_hdmi_clk_enable_v2, + .set_hdmi_codec_pdata = set_hdmi_codec_pdata_v2, .mtk_hdmi_clock_names = mtk_hdmi_clk_names_v2, .num_clocks = MTK_HDMIV2_CLK_COUNT, }; diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi_ddc_v2.c b/drivers/gpu/drm/mediatek/mtk_hdmi_ddc_v2.c index 61696d255e51..26456802a5c4 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi_ddc_v2.c +++ b/drivers/gpu/drm/mediatek/mtk_hdmi_ddc_v2.c @@ -309,7 +309,7 @@ static int mtk_hdmi_ddc_probe(struct platform_device *pdev) ddc->regs = device_node_to_regmap(hdmi); of_node_put(hdmi); if (IS_ERR(ddc->regs)) - return dev_err_probe(dev, PTR_ERR(ddc->regs), "Unable to get mt8195-hdmi syscon"); + return dev_err_probe(dev, PTR_ERR(ddc->regs), "Unable to get hdmi syscon"); ddc->clk = devm_clk_get_enabled(dev, "ddc"); if (IS_ERR(ddc->clk)) diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi_v2.c b/drivers/gpu/drm/mediatek/mtk_hdmi_v2.c index e8457429964d..b391b22fa9f5 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi_v2.c +++ b/drivers/gpu/drm/mediatek/mtk_hdmi_v2.c @@ -211,6 +211,26 @@ static void mtk_hdmi_hw_vid_black(struct mtk_hdmi *hdmi, bool black) mtk_hdmi_mask(hdmi, TOP_VMUTE_CFG1, 0, REG_VMUTE_EN); } +static void mtk_hdmi_hw_aud_mute(struct mtk_hdmi *hdmi) +{ + u32 val; + + val = mtk_hdmi_read(hdmi, AIP_CTRL, &val); + + if (val & DSD_EN) + mtk_hdmi_mask(hdmi, AIP_TXCTRL, + DSD_MUTE_DATA | AUD_MUTE_FIFO_EN, + DSD_MUTE_DATA | AUD_MUTE_FIFO_EN); + else + mtk_hdmi_mask(hdmi, AIP_TXCTRL, AUD_MUTE_FIFO_EN, + AUD_MUTE_FIFO_EN); +} + +static void mtk_hdmi_hw_aud_unmute(struct mtk_hdmi *hdmi) +{ + mtk_hdmi_mask(hdmi, AIP_TXCTRL, AUD_MUTE_DIS, AUD_MUTE_FIFO_EN); +} + static void mtk_hdmi_hw_reset(struct mtk_hdmi *hdmi) { mtk_hdmi_mask(hdmi, HDMITX_CONFIG, 0x0, HDMITX_SW_RSTB); @@ -889,6 +909,7 @@ static void mtk_hdmi_audio_reset(struct mtk_hdmi *hdmi, bool rst) static void mtk_hdmi_aud_output_config(struct mtk_hdmi *hdmi, struct drm_display_mode *display_mode) { + mtk_hdmi_hw_aud_mute(hdmi); mtk_hdmi_aud_enable_packet(hdmi, false); mtk_hdmi_audio_reset(hdmi, true); mtk_hdmi_aip_ctrl_init(hdmi); @@ -901,6 +922,7 @@ static void mtk_hdmi_aud_output_config(struct mtk_hdmi *hdmi, usleep_range(25, 50); mtk_hdmi_aud_on_off_hw_ncts(hdmi, true); mtk_hdmi_aud_enable_packet(hdmi, true); + mtk_hdmi_hw_aud_unmute(hdmi); } void mtk_hdmi_output_init_v2(struct mtk_hdmi *hdmi) @@ -935,6 +957,28 @@ static void mtk_hdmi_reset_colorspace_setting(struct mtk_hdmi *hdmi) hdmi->ycc_quantization_range = HDMI_YCC_QUANTIZATION_RANGE_LIMITED; } +static void mtk_hdmi_audio_enable(struct mtk_hdmi *hdmi) +{ + mtk_hdmi_aud_enable_packet(hdmi, true); + hdmi->audio_enable = true; +} + +static void mtk_hdmi_audio_disable(struct mtk_hdmi *hdmi) +{ + mtk_hdmi_aud_enable_packet(hdmi, false); + hdmi->audio_enable = false; +} + +static void mtk_hdmi_audio_set_param(struct mtk_hdmi *hdmi, +struct hdmi_audio_param *param) +{ + if (!hdmi->audio_enable) + return; + + memcpy(&hdmi->aud_param, param, sizeof(*param)); + mtk_hdmi_aud_output_config(hdmi, &hdmi->mode); +} + static void mtk_hdmi_change_video_resolution(struct mtk_hdmi *hdmi) { bool is_over_340M = false; @@ -955,6 +999,7 @@ static void mtk_hdmi_change_video_resolution(struct mtk_hdmi *hdmi) usleep_range(5, 10); mtk_hdmi_hw_vid_black(hdmi, true); + mtk_hdmi_hw_aud_mute(hdmi); mtk_hdmi_hw_send_av_unmute(hdmi); mtk_hdmi_mask(hdmi, TOP_CFG01, NULL_PKT_VSYNC_HIGH_EN, @@ -1285,6 +1330,7 @@ static void mtk_hdmi_bridge_disable(struct drm_bridge *bridge, mtk_hdmi_hw_send_av_mute(hdmi); usleep_range(5, 50050); mtk_hdmi_hw_vid_black(hdmi, true); + mtk_hdmi_hw_aud_mute(hdmi); mtk_hdmi_disable_hdcp_encr
[PATCH v3 12/12] drm/mediatek: dpi: Add mt8195 hdmi to DPI driver
Add the DPI1 hdmi path support in mtk dpi driver Signed-off-by: Guillaume Ranquet --- drivers/gpu/drm/mediatek/mtk_dpi.c | 143 ++-- drivers/gpu/drm/mediatek/mtk_dpi_regs.h | 5 ++ 2 files changed, 141 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c index 508a6d994e83..8052b47042b8 100644 --- a/drivers/gpu/drm/mediatek/mtk_dpi.c +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c @@ -14,7 +14,10 @@ #include #include #include +#include #include +#include +#include #include @@ -65,10 +68,14 @@ struct mtk_dpi { struct drm_bridge *next_bridge; struct drm_connector *connector; void __iomem *regs; + struct reset_control *reset_ctl; struct device *dev; struct clk *engine_clk; + struct clk *dpi_ck_cg; struct clk *pixel_clk; + struct clk *dpi_sel_clk; struct clk *tvd_clk; + struct clk *hdmi_cg; int irq; struct drm_display_mode mode; const struct mtk_dpi_conf *conf; @@ -134,6 +141,7 @@ struct mtk_dpi_yc_limit { * @yuv422_en_bit: Enable bit of yuv422. * @csc_enable_bit: Enable bit of CSC. * @pixels_per_iter: Quantity of transferred pixels per iteration. + * @is_internal_hdmi: True if this DPI block is directly connected to SoC internal HDMI block */ struct mtk_dpi_conf { unsigned int (*cal_factor)(int clock); @@ -152,6 +160,7 @@ struct mtk_dpi_conf { u32 yuv422_en_bit; u32 csc_enable_bit; u32 pixels_per_iter; + bool is_internal_hdmi; }; static void mtk_dpi_mask(struct mtk_dpi *dpi, u32 offset, u32 val, u32 mask) @@ -465,8 +474,15 @@ static void mtk_dpi_power_off(struct mtk_dpi *dpi) pinctrl_select_state(dpi->pinctrl, dpi->pins_gpio); mtk_dpi_disable(dpi); + + reset_control_rearm(dpi->reset_ctl); + clk_disable_unprepare(dpi->pixel_clk); clk_disable_unprepare(dpi->engine_clk); + clk_disable_unprepare(dpi->dpi_sel_clk); + clk_disable_unprepare(dpi->dpi_ck_cg); + clk_disable_unprepare(dpi->hdmi_cg); + clk_disable_unprepare(dpi->tvd_clk); } static int mtk_dpi_power_on(struct mtk_dpi *dpi) @@ -482,12 +498,44 @@ static int mtk_dpi_power_on(struct mtk_dpi *dpi) goto err_refcount; } + ret = clk_prepare_enable(dpi->dpi_sel_clk); + if (ret) { + dev_err(dpi->dev, "failed to enable dpi_sel clock: %d\n", ret); + goto err_refcount; + } + + ret = clk_prepare_enable(dpi->tvd_clk); + if (ret) { + dev_err(dpi->dev, "Failed to enable tvd pll: %d\n", ret); + goto err_tvd; + } + + ret = clk_prepare_enable(dpi->engine_clk); + if (ret) { + dev_err(dpi->dev, "Failed to enable engine clock: %d\n", ret); + goto err_engine; + } + + ret = clk_prepare_enable(dpi->hdmi_cg); + if (ret) { + dev_err(dpi->dev, "Failed to enable hdmi_cg clock: %d\n", ret); + goto err_hdmi_cg; + } + + ret = clk_prepare_enable(dpi->dpi_ck_cg); + if (ret) { + dev_err(dpi->dev, "Failed to enable dpi_ck_cg clock: %d\n", ret); + goto err_ck_cg; + } + ret = clk_prepare_enable(dpi->pixel_clk); if (ret) { dev_err(dpi->dev, "Failed to enable pixel clock: %d\n", ret); goto err_pixel; } + reset_control_reset(dpi->reset_ctl); + if (dpi->pinctrl && dpi->pins_dpi) pinctrl_select_state(dpi->pinctrl, dpi->pins_dpi); @@ -495,6 +543,15 @@ static int mtk_dpi_power_on(struct mtk_dpi *dpi) err_pixel: clk_disable_unprepare(dpi->engine_clk); + clk_disable_unprepare(dpi->dpi_ck_cg); +err_ck_cg: + clk_disable_unprepare(dpi->hdmi_cg); +err_hdmi_cg: + clk_disable_unprepare(dpi->engine_clk); +err_engine: + clk_disable_unprepare(dpi->tvd_clk); +err_tvd: + clk_disable_unprepare(dpi->dpi_sel_clk); err_refcount: dpi->refcount--; return ret; @@ -538,7 +595,6 @@ static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi, else clk_set_rate(dpi->pixel_clk, vm.pixelclock); - vm.pixelclock = clk_get_rate(dpi->pixel_clk); dev_dbg(dpi->dev, "Got PLL %lu Hz, pixel clock %lu Hz\n", @@ -605,7 +661,16 @@ static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi, if (dpi->conf->support_direct_pin) { mtk_dpi_config_yc_map(dpi, dpi->yc_map); mtk_dpi_config_2n_h_fre(dpi); - mtk_dpi_dual_edge(dpi); + /* DPI could be connecting to external bridge +* or internal HDMI encoder. */ + if (dpi->conf->is_internal_hdmi) { + mtk_dpi_mask(dpi, DPI_CON, DPI_OUTPUT_1T1P_EN, +DPI_OUTPUT_1T1P_EN); +
[PATCH v3 09/12] phy: phy-mtk-hdmi: Add generic phy configure callback
Some phys, such as mt8195, needs to have a configure callback defined. Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Guillaume Ranquet --- drivers/phy/mediatek/phy-mtk-hdmi.c | 12 drivers/phy/mediatek/phy-mtk-hdmi.h | 1 + 2 files changed, 13 insertions(+) diff --git a/drivers/phy/mediatek/phy-mtk-hdmi.c b/drivers/phy/mediatek/phy-mtk-hdmi.c index b16d437d6721..32f713301768 100644 --- a/drivers/phy/mediatek/phy-mtk-hdmi.c +++ b/drivers/phy/mediatek/phy-mtk-hdmi.c @@ -8,10 +8,12 @@ static int mtk_hdmi_phy_power_on(struct phy *phy); static int mtk_hdmi_phy_power_off(struct phy *phy); +static int mtk_hdmi_phy_configure(struct phy *phy, union phy_configure_opts *opts); static const struct phy_ops mtk_hdmi_phy_dev_ops = { .power_on = mtk_hdmi_phy_power_on, .power_off = mtk_hdmi_phy_power_off, + .configure = mtk_hdmi_phy_configure, .owner = THIS_MODULE, }; @@ -43,6 +45,16 @@ static int mtk_hdmi_phy_power_off(struct phy *phy) return 0; } +static int mtk_hdmi_phy_configure(struct phy *phy, union phy_configure_opts *opts) +{ + struct mtk_hdmi_phy *hdmi_phy = phy_get_drvdata(phy); + + if (hdmi_phy->conf->hdmi_phy_configure) + return hdmi_phy->conf->hdmi_phy_configure(phy, opts); + + return 0; +} + static const struct phy_ops * mtk_hdmi_phy_dev_get_ops(const struct mtk_hdmi_phy *hdmi_phy) { diff --git a/drivers/phy/mediatek/phy-mtk-hdmi.h b/drivers/phy/mediatek/phy-mtk-hdmi.h index c7fa65cff989..f5aac9d352d8 100644 --- a/drivers/phy/mediatek/phy-mtk-hdmi.h +++ b/drivers/phy/mediatek/phy-mtk-hdmi.h @@ -24,6 +24,7 @@ struct mtk_hdmi_phy_conf { const struct clk_ops *hdmi_phy_clk_ops; void (*hdmi_phy_enable_tmds)(struct mtk_hdmi_phy *hdmi_phy); void (*hdmi_phy_disable_tmds)(struct mtk_hdmi_phy *hdmi_phy); + int (*hdmi_phy_configure)(struct phy *phy, union phy_configure_opts *opts); }; struct mtk_hdmi_phy { -- b4 0.11.0-dev
[PATCH v3 06/12] drm/mediatek: hdmi: add frame_colorimetry flag
Add a flag to indicate support for frame colorimetry. Signed-off-by: Guillaume Ranquet --- drivers/gpu/drm/mediatek/mtk_hdmi_common.c | 11 +++ drivers/gpu/drm/mediatek/mtk_hdmi_common.h | 1 + 2 files changed, 12 insertions(+) diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi_common.c b/drivers/gpu/drm/mediatek/mtk_hdmi_common.c index 3635ca66817b..933c51b5f6d7 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi_common.c +++ b/drivers/gpu/drm/mediatek/mtk_hdmi_common.c @@ -120,6 +120,17 @@ int mtk_hdmi_setup_avi_infoframe(struct mtk_hdmi *hdmi, u8 *buffer, size_t bufsz return err; } + if (hdmi->conf->has_frame_colorimetry) { + frame.colorimetry = hdmi->colorimtery; + if (frame.colorimetry == HDMI_COLORIMETRY_EXTENDED) + frame.extended_colorimetry = hdmi->extended_colorimetry; + + /* quantiation range:limited or full */ + if (frame.colorspace == HDMI_COLORSPACE_RGB) + frame.quantization_range = hdmi->quantization_range; + else + frame.ycc_quantization_range = hdmi->ycc_quantization_range; + } err = hdmi_avi_infoframe_pack(&frame, buffer, bufsz); if (err < 0) { diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi_common.h b/drivers/gpu/drm/mediatek/mtk_hdmi_common.h index 921bde150e11..2e8e5feec377 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi_common.h +++ b/drivers/gpu/drm/mediatek/mtk_hdmi_common.h @@ -32,6 +32,7 @@ struct mtk_hdmi_conf { bool tz_disabled; bool cea_modes_only; bool has_cec; + bool has_frame_colorimetry; unsigned long max_mode_clock; const struct drm_bridge_funcs *bridge_funcs; void (*mtk_hdmi_output_init)(struct mtk_hdmi *hdmi); -- b4 0.11.0-dev
[PATCH v3 07/12] drm/mediatek: hdmi: add v2 support
Adds hdmi and hdmi-ddc support for v2 IP. Signed-off-by: Guillaume Ranquet --- drivers/gpu/drm/mediatek/Makefile |2 + drivers/gpu/drm/mediatek/mtk_hdmi_common.c | 14 + drivers/gpu/drm/mediatek/mtk_hdmi_common.h |1 + drivers/gpu/drm/mediatek/mtk_hdmi_ddc_v2.c | 367 +++ drivers/gpu/drm/mediatek/mtk_hdmi_regs_v2.h | 309 ++ drivers/gpu/drm/mediatek/mtk_hdmi_v2.c | 1379 +++ drivers/gpu/drm/mediatek/mtk_hdmi_v2.h | 29 + 7 files changed, 2101 insertions(+) diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile index 79bbaa58893e..bb60856b629e 100644 --- a/drivers/gpu/drm/mediatek/Makefile +++ b/drivers/gpu/drm/mediatek/Makefile @@ -24,6 +24,8 @@ mediatek-drm-hdmi-objs := mtk_cec.o \ mtk_hdmi.o \ mtk_hdmi_common.o \ mtk_hdmi_ddc.o \ + mtk_hdmi_ddc_v2.o \ + mtk_hdmi_v2.o \ obj-$(CONFIG_DRM_MEDIATEK_HDMI) += mediatek-drm-hdmi.o diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi_common.c b/drivers/gpu/drm/mediatek/mtk_hdmi_common.c index 933c51b5f6d7..e43c938a9aa5 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi_common.c +++ b/drivers/gpu/drm/mediatek/mtk_hdmi_common.c @@ -380,6 +380,16 @@ static const struct mtk_hdmi_conf mtk_hdmi_conf_mt8173 = { .num_clocks = MTK_HDMIV1_CLK_COUNT, }; +static const struct mtk_hdmi_conf mtk_hdmi_conf_v2 = { + .has_frame_colorimetry = true, + .bridge_funcs = &mtk_v2_hdmi_bridge_funcs, + .mtk_hdmi_output_init = mtk_hdmi_output_init_v2, + .mtk_hdmi_clk_disable = mtk_hdmi_clk_disable_v2, + .mtk_hdmi_clk_enable = mtk_hdmi_clk_enable_v2, + .mtk_hdmi_clock_names = mtk_hdmi_clk_names_v2, + .num_clocks = MTK_HDMIV2_CLK_COUNT, +}; + static const struct of_device_id mtk_drm_hdmi_of_ids[] = { { .compatible = "mediatek,mt2701-hdmi", .data = &mtk_hdmi_conf_mt2701, @@ -390,6 +400,9 @@ static const struct of_device_id mtk_drm_hdmi_of_ids[] = { { .compatible = "mediatek,mt8173-hdmi", .data = &mtk_hdmi_conf_mt8173, }, + { .compatible = "mediatek,mt8195-hdmi", + .data = &mtk_hdmi_conf_v2, + }, {} }; MODULE_DEVICE_TABLE(of, mtk_drm_hdmi_of_ids); @@ -438,6 +451,7 @@ static struct platform_driver mtk_hdmi_driver = { static struct platform_driver * const mtk_hdmi_drivers[] = { &mtk_hdmi_ddc_driver, &mtk_cec_driver, + &mtk_hdmi_ddc_v2_driver, &mtk_hdmi_driver, }; diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi_common.h b/drivers/gpu/drm/mediatek/mtk_hdmi_common.h index 2e8e5feec377..d030b71b5231 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi_common.h +++ b/drivers/gpu/drm/mediatek/mtk_hdmi_common.h @@ -27,6 +27,7 @@ #include "mtk_cec.h" #include "mtk_hdmi.h" +#include "mtk_hdmi_v2.h" struct mtk_hdmi_conf { bool tz_disabled; diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi_ddc_v2.c b/drivers/gpu/drm/mediatek/mtk_hdmi_ddc_v2.c new file mode 100644 index ..61696d255e51 --- /dev/null +++ b/drivers/gpu/drm/mediatek/mtk_hdmi_ddc_v2.c @@ -0,0 +1,367 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2021 MediaTek Inc. + * Copyright (c) 2021 BayLibre, SAS + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "mtk_hdmi_regs_v2.h" +#include "mtk_hdmi_v2.h" + +#define EDID_ID 0x50 +#define DDC2_CLOK 572 /* BIM=208M/(v*4) = 90Khz */ +#define DDC2_CLOK_EDID 832 /* BIM=208M/(v*4) = 62.5Khz */ + +struct mtk_hdmi_ddc { + struct device *dev; + /* Serialize read/write operations */ + struct mutex mtx; + struct i2c_adapter adap; + struct clk *clk; + void __iomem *regs; +}; + +enum sif_bit_t_hdmi { + SIF_8_BIT_HDMI, /* /< [8 bits data address.] */ + SIF_16_BIT_HDMI, /* /< [16 bits data address.] */ +}; + +static void hdmi_ddc_request(struct mtk_hdmi_ddc *ddc) +{ + regmap_update_bits(ddc->regs, HDCP2X_POL_CTRL, HDCP2X_DIS_POLL_EN, +HDCP2X_DIS_POLL_EN); +} + +static void mtk_ddc_wr_one(struct mtk_hdmi_ddc *ddc, unsigned int addr_id, + unsigned int offset_id, unsigned char wr_data) +{ + u32 val; + + regmap_read(ddc->regs, HDCP2X_DDCM_STATUS, &val); + + if (val & DDC_I2C_BUS_LOW) { + regmap_update_bits(ddc->regs, DDC_CTRL, FIELD_PREP(DDC_CMD, CLOCK_SCL), DDC_CMD); + usleep_range(250, 300); + } + regmap_update_bits(ddc->regs, HPD_DDC_CTRL, FIELD_PREP(DDC_DELAY_CNT, DDC2_CLOK), DDC_DELAY_CNT); + regmap_write(ddc->regs, SI2C_CTRL, FIELD_PREP(SI2C_ADDR, SI2C_ADDR_READ)); + regmap_update_bits(ddc->regs, SI2C_CTRL, FIELD_PREP(SI2C_WDATA, wr_data), SI2C_WDATA); +
[PATCH v3 05/12] drm/mediatek: hdmi: make the cec dev optional
Make cec device optional in order to support newer versions of the hdmi IP which doesn't require it Signed-off-by: Guillaume Ranquet --- drivers/gpu/drm/mediatek/mtk_hdmi.c| 8 +++-- drivers/gpu/drm/mediatek/mtk_hdmi_common.c | 54 -- drivers/gpu/drm/mediatek/mtk_hdmi_common.h | 1 + 3 files changed, 42 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c index 73bda2849196..85c6ebca36dd 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c @@ -927,10 +927,11 @@ void mtk_hdmi_clk_disable_audio_mt8183(struct mtk_hdmi *hdmi) static enum drm_connector_status mtk_hdmi_update_plugged_status(struct mtk_hdmi *hdmi) { - bool connected; + bool connected = true; mutex_lock(&hdmi->update_plugged_status_lock); - connected = mtk_cec_hpd_high(hdmi->cec_dev); + if (hdmi->cec_dev) + connected = mtk_cec_hpd_high(hdmi->cec_dev); if (hdmi->plugged_cb && hdmi->codec_dev) hdmi->plugged_cb(hdmi->codec_dev, connected); mutex_unlock(&hdmi->update_plugged_status_lock); @@ -1025,7 +1026,8 @@ static int mtk_hdmi_bridge_attach(struct drm_bridge *bridge, return ret; } - mtk_cec_set_hpd_event(hdmi->cec_dev, mtk_hdmi_hpd_event, hdmi->dev); + if (hdmi->cec_dev) + mtk_cec_set_hpd_event(hdmi->cec_dev, mtk_hdmi_hpd_event, hdmi->dev); return 0; } diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi_common.c b/drivers/gpu/drm/mediatek/mtk_hdmi_common.c index 3f08d37b1af0..3635ca66817b 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi_common.c +++ b/drivers/gpu/drm/mediatek/mtk_hdmi_common.c @@ -137,28 +137,18 @@ void mtk_hdmi_send_infoframe(struct mtk_hdmi *hdmi, u8 *buffer_spd, size_t bufsz mtk_hdmi_setup_spd_infoframe(hdmi, buffer_spd, bufsz_spd, "mediatek", "On-chip HDMI"); } -int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi, struct platform_device *pdev, - const char *const *clk_names, size_t num_clocks) +static int mtk_hdmi_get_cec_dev(struct mtk_hdmi *hdmi, struct device *dev, struct device_node *np) { - struct device *dev = &pdev->dev; - struct device_node *np = dev->of_node; - struct device_node *cec_np, *remote, *i2c_np; + int ret; + struct device_node *cec_np; struct platform_device *cec_pdev; struct regmap *regmap; - struct resource *mem; - int ret; - - ret = mtk_hdmi_get_all_clk(hdmi, np, clk_names, num_clocks); - if (ret) { - dev_err(dev, "Failed to get all clks\n"); - return ret; - } /* The CEC module handles HDMI hotplug detection */ cec_np = of_get_compatible_child(np->parent, "mediatek,mt8173-cec"); if (!cec_np) { dev_err(dev, "Failed to find CEC node\n"); - return -EINVAL; + return -ENOTSUPP; } cec_pdev = of_find_device_by_node(cec_np); @@ -168,7 +158,6 @@ int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi, struct platform_device *pdev, return -EPROBE_DEFER; } of_node_put(cec_np); - hdmi->cec_dev = &cec_pdev->dev; /* * The mediatek,syscon-hdmi property contains a phandle link to the * MMSYS_CONFIG device and the register offset of the HDMI_SYS_CFG @@ -177,12 +166,41 @@ int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi, struct platform_device *pdev, regmap = syscon_regmap_lookup_by_phandle(np, "mediatek,syscon-hdmi"); ret = of_property_read_u32_index(np, "mediatek,syscon-hdmi", 1, &hdmi->sys_offset); if (IS_ERR(regmap)) - ret = PTR_ERR(regmap); + return PTR_ERR(regmap); if (ret) { - dev_err(dev, "Failed to get system configuration registers: %d\n", ret); - goto put_device; + dev_err(dev, + "Failed to get system configuration registers: %d\n", ret); + return ret; } + hdmi->sys_regmap = regmap; + hdmi->cec_dev = &cec_pdev->dev; + + return 0; +} + +int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi, struct platform_device *pdev, + const char *const *clk_names, size_t num_clocks) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct device_node *remote, *i2c_np; + struct resource *mem; + int ret; + + ret = mtk_hdmi_get_all_clk(hdmi, np, clk_names, num_clocks); + if (ret) { + dev_err(dev, "Failed to get all clks\n"); + return ret; + } + + ret = mtk_hdmi_get_cec_dev(hdmi, dev, np); + if (ret) { + if (ret == -ENOTSUPP) + dev_info(dev, "No CEC node found, continuing without"); + else
[PATCH v3 03/12] drm/mediatek: hdmi: use a regmap instead of iomem
To prepare support for newer chips that need to share their address range with a dedicated ddc driver, use a regmap. Signed-off-by: Guillaume Ranquet --- drivers/gpu/drm/mediatek/mtk_hdmi.c | 43 +++-- 1 file changed, 13 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c index 4c80b6896dc3..9b02b30a193a 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c @@ -171,7 +171,7 @@ struct mtk_hdmi { u32 ibias_up; struct regmap *sys_regmap; unsigned int sys_offset; - void __iomem *regs; + struct regmap *regs; enum hdmi_colorspace csp; struct hdmi_audio_param aud_param; bool audio_enable; @@ -187,44 +187,29 @@ static inline struct mtk_hdmi *hdmi_ctx_from_bridge(struct drm_bridge *b) return container_of(b, struct mtk_hdmi, bridge); } -static u32 mtk_hdmi_read(struct mtk_hdmi *hdmi, u32 offset) +static int mtk_hdmi_read(struct mtk_hdmi *hdmi, u32 offset, u32 *val) { - return readl(hdmi->regs + offset); + return regmap_read(hdmi->regs, offset, val); } static void mtk_hdmi_write(struct mtk_hdmi *hdmi, u32 offset, u32 val) { - writel(val, hdmi->regs + offset); + regmap_write(hdmi->regs, offset, val); } static void mtk_hdmi_clear_bits(struct mtk_hdmi *hdmi, u32 offset, u32 bits) { - void __iomem *reg = hdmi->regs + offset; - u32 tmp; - - tmp = readl(reg); - tmp &= ~bits; - writel(tmp, reg); + regmap_clear_bits(hdmi->regs, offset, bits); } static void mtk_hdmi_set_bits(struct mtk_hdmi *hdmi, u32 offset, u32 bits) { - void __iomem *reg = hdmi->regs + offset; - u32 tmp; - - tmp = readl(reg); - tmp |= bits; - writel(tmp, reg); + regmap_set_bits(hdmi->regs, offset, bits); } static void mtk_hdmi_mask(struct mtk_hdmi *hdmi, u32 offset, u32 val, u32 mask) { - void __iomem *reg = hdmi->regs + offset; - u32 tmp; - - tmp = readl(reg); - tmp = (tmp & ~mask) | (val & mask); - writel(tmp, reg); + regmap_update_bits(hdmi->regs, offset, mask, val); } static void mtk_hdmi_hw_vid_black(struct mtk_hdmi *hdmi, bool black) @@ -473,7 +458,7 @@ static void mtk_hdmi_hw_aud_set_i2s_fmt(struct mtk_hdmi *hdmi, { u32 val; - val = mtk_hdmi_read(hdmi, GRL_CFG0); + mtk_hdmi_read(hdmi, GRL_CFG0, &val); val &= ~(CFG0_W_LENGTH_MASK | CFG0_I2S_MODE_MASK); switch (i2s_fmt) { @@ -565,7 +550,7 @@ static void mtk_hdmi_hw_aud_set_input_type(struct mtk_hdmi *hdmi, { u32 val; - val = mtk_hdmi_read(hdmi, GRL_CFG1); + mtk_hdmi_read(hdmi, GRL_CFG1, &val); if (input_type == HDMI_AUD_INPUT_I2S && (val & CFG1_SPDIF) == CFG1_SPDIF) { val &= ~CFG1_SPDIF; @@ -596,7 +581,7 @@ static void mtk_hdmi_hw_aud_src_reenable(struct mtk_hdmi *hdmi) { u32 val; - val = mtk_hdmi_read(hdmi, GRL_MIX_CTRL); + mtk_hdmi_read(hdmi, GRL_MIX_CTRL, &val); if (val & MIX_CTRL_SRC_EN) { val &= ~MIX_CTRL_SRC_EN; mtk_hdmi_write(hdmi, GRL_MIX_CTRL, val); @@ -610,7 +595,7 @@ static void mtk_hdmi_hw_aud_src_disable(struct mtk_hdmi *hdmi) { u32 val; - val = mtk_hdmi_read(hdmi, GRL_MIX_CTRL); + mtk_hdmi_read(hdmi, GRL_MIX_CTRL, &val); val &= ~MIX_CTRL_SRC_EN; mtk_hdmi_write(hdmi, GRL_MIX_CTRL, val); mtk_hdmi_write(hdmi, GRL_SHIFT_L1, 0x00); @@ -621,7 +606,7 @@ static void mtk_hdmi_hw_aud_set_mclk(struct mtk_hdmi *hdmi, { u32 val; - val = mtk_hdmi_read(hdmi, GRL_CFG5); + mtk_hdmi_read(hdmi, GRL_CFG5, &val); val &= CFG5_CD_RATIO_MASK; switch (mclk) { @@ -1427,7 +1412,6 @@ static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi, struct device_node *cec_np, *remote, *i2c_np; struct platform_device *cec_pdev; struct regmap *regmap; - struct resource *mem; int ret; ret = mtk_hdmi_get_all_clk(hdmi, np); @@ -1473,8 +1457,7 @@ static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi, } hdmi->sys_regmap = regmap; - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - hdmi->regs = devm_ioremap_resource(dev, mem); + hdmi->regs = device_node_to_regmap(dev->of_node); if (IS_ERR(hdmi->regs)) { ret = PTR_ERR(hdmi->regs); goto put_device; -- b4 0.11.0-dev
[PATCH v3 02/12] dt-bindings: display: mediatek: add MT8195 hdmi bindings
Add mt8195 SoC bindings for hdmi and hdmi-ddc On mt8195 the ddc i2c controller is part of the hdmi IP block and thus has no specific register range, power domain or interrupt, making it simpler than its the legacy "mediatek,hdmi-ddc" binding. Signed-off-by: Guillaume Ranquet --- .../bindings/display/mediatek/mediatek,hdmi.yaml | 61 ++ .../display/mediatek/mediatek,mt8195-hdmi-ddc.yaml | 51 ++ 2 files changed, 101 insertions(+), 11 deletions(-) diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,hdmi.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,hdmi.yaml index bdaf0b51e68c..9710b7b6e9bf 100644 --- a/Documentation/devicetree/bindings/display/mediatek/mediatek,hdmi.yaml +++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,hdmi.yaml @@ -21,6 +21,7 @@ properties: - mediatek,mt7623-hdmi - mediatek,mt8167-hdmi - mediatek,mt8173-hdmi + - mediatek,mt8195-hdmi reg: maxItems: 1 @@ -29,18 +30,12 @@ properties: maxItems: 1 clocks: -items: - - description: Pixel Clock - - description: HDMI PLL - - description: Bit Clock - - description: S/PDIF Clock +minItems: 4 +maxItems: 4 clock-names: -items: - - const: pixel - - const: pll - - const: bclk - - const: spdif +minItems: 4 +maxItems: 4 phys: maxItems: 1 @@ -58,6 +53,9 @@ properties: description: | phandle link and register offset to the system configuration registers. + power-domains: +maxItems: 1 + ports: $ref: /schemas/graph.yaml#/properties/ports @@ -86,9 +84,50 @@ required: - clock-names - phys - phy-names - - mediatek,syscon-hdmi - ports +allOf: + - if: + properties: +compatible: + contains: +const: mediatek,mt8195-hdmi +then: + properties: +clocks: + items: +- description: APB +- description: HDCP +- description: HDCP 24M +- description: Split HDMI +clock-names: + items: +- const: hdmi_apb_sel +- const: hdcp_sel +- const: hdcp24_sel +- const: split_hdmi + + required: +- power-domains +else: + properties: +clocks: + items: +- description: Pixel Clock +- description: HDMI PLL +- description: Bit Clock +- description: S/PDIF Clock + +clock-names: + items: +- const: pixel +- const: pll +- const: bclk +- const: spdif + + required: +- mediatek,syscon-hdmi + additionalProperties: false examples: diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,mt8195-hdmi-ddc.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,mt8195-hdmi-ddc.yaml new file mode 100644 index ..2dc273689584 --- /dev/null +++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,mt8195-hdmi-ddc.yaml @@ -0,0 +1,51 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/mediatek/mediatek,mt8195-hdmi-ddc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Mediatek HDMI DDC for mt8195 + +maintainers: + - CK Hu + - Jitao shi + +description: | + The HDMI DDC i2c controller is used to interface with the HDMI DDC pins. + +properties: + compatible: +enum: + - mediatek,mt8195-hdmi-ddc + + clocks: +maxItems: 1 + + clock-names: +items: + - const: ddc + + mediatek,hdmi: +$ref: /schemas/types.yaml#/definitions/phandle +description: + A phandle to the mt8195 hdmi controller + +required: + - compatible + - clocks + - clock-names + +additionalProperties: false + +examples: + - | +#include +#include +hdmiddc0: i2c { + compatible = "mediatek,mt8195-hdmi-ddc"; + mediatek,hdmi = <&hdmi0>; + clocks = <&clk26m>; + clock-names = "ddc"; +}; + +... -- b4 0.11.0-dev
[PATCH v3 01/12] dt-bindings: phy: mediatek: hdmi-phy: Add mt8195 compatible
Add a compatible for the HDMI PHY on MT8195 Acked-by: Krzysztof Kozlowski Signed-off-by: Guillaume Ranquet --- Documentation/devicetree/bindings/phy/mediatek,hdmi-phy.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/phy/mediatek,hdmi-phy.yaml b/Documentation/devicetree/bindings/phy/mediatek,hdmi-phy.yaml index 0d94950b84ca..71c75a11e189 100644 --- a/Documentation/devicetree/bindings/phy/mediatek,hdmi-phy.yaml +++ b/Documentation/devicetree/bindings/phy/mediatek,hdmi-phy.yaml @@ -28,6 +28,7 @@ properties: - const: mediatek,mt2701-hdmi-phy - const: mediatek,mt2701-hdmi-phy - const: mediatek,mt8173-hdmi-phy + - const: mediatek,mt8195-hdmi-phy reg: maxItems: 1 -- b4 0.11.0-dev