From 5313e1d0975f9c98b5c86179ff3584abae47dafa Mon Sep 17 00:00:00 2001 From: Zhang Yubing Date: Wed, 6 Nov 2024 19:54:12 +0800 Subject: [PATCH] drm/rockchip: logo: add the effect bridge state for atomic state Some display interface driver will register encoder and bridge. The analogix edp driver is one of these driver and it will use the bridge state in atomic_check callback. If no bridge state get, the atomic_check will return without assign a value to the crtc_state.output_type. When enable uboot logo, if no bridge state get for the analogix edp, the old_crtc_state.output_type will be 0 and the new_crtc_state.output_type will be DRM_MODE_CONNECTOR_eDP. It assume that this different will affect nothing. But when the edp attach to VOPB/L and assign the VOPB/L dclk parent as VPLL, the crtc atomic_check callback will change the VOPB/L dclk parent and issue a mode change. this mode change will call the edp driver encoder_disable callback and reference the encoder.crtc pointer. This point only assign a value in drm_atomic_helper_update_legacy_modeset_state(). So a NULL pointer issue will happen as follow: [ 3.489609] Unable to handle kernel NULL pointer dereference at virtual address 00000000000005c8 [ 3.585216] Mem abort info: [ 3.585219] ESR = 0x0000000096000005 [ 3.585223] EC = 0x25: DABT (current EL), IL = 32 bits [ 3.585227] SET = 0, FnV = 0 [ 3.585230] EA = 0, S1PTW = 0 [ 3.585232] FSC = 0x05: level 1 translation fault [ 3.585235] Data abort info: [ 3.585237] ISV = 0, ISS = 0x00000005 [ 3.585240] CM = 0, WnR = 0 [ 3.586697] mmcblk0rpmb: mmc0:0001 AJTD4R 4.00 MiB, chardev (235:0) [ 3.587117] [00000000000005c8] user address but active_mm is swapper [ 3.587121] Internal error: Oops: 0000000096000005 [#1] SMP [ 3.592746] Modules linked in: [ 3.593023] CPU: 5 PID: 46 Comm: kworker/u12:1 Not tainted 6.1.99 #517 [ 3.593595] Hardware name: Rockchip RK3399 EVB IND LPDDR4 Board edp (Linux) (DT) [ 3.594244] Workqueue: events_unbound deferred_probe_work_func [ 3.594764] pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) [ 3.595380] pc : rockchip_dp_drm_encoder_disable+0x20/0x10c [ 3.595874] lr : drm_atomic_helper_commit_modeset_disables+0x1e0/0x670 [ 3.596444] sp : ffffffc00a71b6b0 [ 3.596741] x29: ffffffc00a71b6b0 x28: ffffff80049ce200 x27: 0000000000000038 [ 3.597370] x26: ffffff8003091810 x25: ffffff8004d27c98 x24: 0000000000000000 [ 3.597999] x23: 0000000000000000 x22: ffffffc009971ade x21: ffffffc00991a755 [ 3.598628] x20: ffffff80049c9c80 x19: ffffff8004d27c98 x18: ffffff8003154090 [ 3.599257] x17: 685f63696d6f7461 x16: ffffffffffffffff x15: ffffff800a2f4400 [ 3.599885] x14: 0000000000000000 x13: 0000000000000350 x12: 000000000104202a [ 3.600514] x11: 0000000000800000 x10: 0000000000000000 x9 : ffffffc0087ef158 [ 3.601143] x8 : 0000000000000000 x7 : 72205d3536353938 x6 : 0000000000000000 [ 3.601771] x5 : 0000000000000000 x4 : 0000000000000000 x3 : ffffffc00a71b5a0 [ 3.602399] x2 : ffffff8002cac4c0 x1 : ffffff80049c9c80 x0 : ffffff8004d27c98 [ 3.603027] Call trace: [ 3.603245] rockchip_dp_drm_encoder_disable+0x20/0x10c [ 3.603704] drm_atomic_helper_commit_modeset_disables+0x1e0/0x670 [ 3.604250] rockchip_drm_atomic_helper_commit_tail_rpm+0x4c/0x2d8 [ 3.604799] commit_tail+0xa8/0x154 [ 3.605108] drm_atomic_helper_commit+0x1c8/0x1e4 [ 3.605519] drm_atomic_commit+0xa8/0xd0 [ 3.605864] rockchip_drm_show_logo+0x1a98/0x1c50 [ 3.606276] rockchip_drm_bind+0x1fc/0x2ac [ 3.606643] try_to_bring_up_aggregate_device+0x1f8/0x28c [ 3.607123] __component_add+0xc4/0x180 [ 3.607467] component_add+0x18/0x20 [ 3.607788] rockchip_dp_probe+0x41c/0x480 [ 3.608154] platform_probe+0xa8/0xd0 [ 3.608476] really_probe+0x168/0x3f8 [ 3.608798] __driver_probe_device+0xa4/0x164 [ 3.609186] driver_probe_device+0x40/0x210 [ 3.609553] __device_attach_driver+0x12c/0x1c0 [ 3.609954] bus_for_each_drv+0x88/0xd0 [ 3.610299] __device_attach+0xd4/0x1c0 [ 3.610642] device_initial_probe+0x18/0x20 [ 3.611009] bus_probe_device+0x38/0x98 [ 3.611354] deferred_probe_work_func+0xa4/0xf8 [ 3.611754] process_one_work+0x1e0/0x400 [ 3.612112] worker_thread+0x340/0x55c [ 3.612445] kthread+0xcc/0x204 [ 3.612722] ret_from_fork+0x10/0x20 To avoid this issue, a method is to add the effect bridge state when show logo. Fixes: a7620fa846c2 ("drm/rockchip: analogix_dp: add support for color format yuv444/yuv422") Change-Id: Ie1f1ce5a8a21809a146acd48f3ee94d1a8879eb6 Signed-off-by: Zhang Yubing --- drivers/gpu/drm/rockchip/rockchip_drm_logo.c | 27 ++++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_logo.c b/drivers/gpu/drm/rockchip/rockchip_drm_logo.c index 8d2e680bcdf0..9d74f40a0350 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_logo.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_logo.c @@ -991,19 +991,35 @@ static int update_state(struct drm_device *drm_dev, { struct drm_crtc *crtc = set->crtc; struct drm_connector *connector = set->sub_dev->connector; + struct drm_encoder *encoder; struct drm_display_mode *mode = set->mode; struct drm_plane_state *primary_state; struct drm_crtc_state *crtc_state; struct drm_connector_state *conn_state; + const struct drm_connector_helper_funcs *connector_helper_funcs; int ret; struct rockchip_crtc_state *s; + connector_helper_funcs = connector->helper_private; + if (!connector_helper_funcs) + return -ENXIO; + if (connector_helper_funcs->best_encoder) + encoder = connector_helper_funcs->best_encoder(connector); + else + encoder = rockchip_drm_connector_get_single_encoder(connector); + if (!encoder) + return -ENXIO; + crtc_state = drm_atomic_get_crtc_state(state, crtc); if (IS_ERR(crtc_state)) return PTR_ERR(crtc_state); conn_state = drm_atomic_get_connector_state(state, connector); if (IS_ERR(conn_state)) return PTR_ERR(conn_state); + ret = drm_atomic_add_encoder_bridges(state, encoder); + if (ret) + return ret; + s = to_rockchip_crtc_state(crtc_state); s->left_margin = set->left_margin; s->right_margin = set->right_margin; @@ -1022,19 +1038,8 @@ static int update_state(struct drm_device *drm_dev, crtc_state->active = true; } else { const struct drm_encoder_helper_funcs *encoder_helper_funcs; - const struct drm_connector_helper_funcs *connector_helper_funcs; - struct drm_encoder *encoder; struct drm_bridge *bridge; - connector_helper_funcs = connector->helper_private; - if (!connector_helper_funcs) - return -ENXIO; - if (connector_helper_funcs->best_encoder) - encoder = connector_helper_funcs->best_encoder(connector); - else - encoder = rockchip_drm_connector_get_single_encoder(connector); - if (!encoder) - return -ENXIO; encoder_helper_funcs = encoder->helper_private; if (!encoder_helper_funcs->atomic_check) return -ENXIO;