From: Xiaomeng Tong xiam0nd.tong@gmail.com
stable inclusion from stable-v5.10.121 commit 4e2fbe8cda17d7cfae7429c6d0ac8a11be50cb15 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I5L6CQ
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=...
--------------------------------
commit 2e6c86be0e57079d1fb6c7c7e5423db096d0548a upstream.
The two bugs are here: if (encoder) { if (bridge && bridge->timings)
The list iterator value 'encoder/bridge' will *always* be set and non-NULL by drm_for_each_encoder()/list_for_each_entry(), so it is incorrect to assume that the iterator value will be NULL if the list is empty or no element is found.
To fix the bug, use a new variable '*_iter' as the list iterator, while use the old variable 'encoder/bridge' as a dedicated pointer to point to the found element.
Cc: stable@vger.kernel.org Fixes: 99e360442f223 ("drm/stm: Fix bus_flags handling") Signed-off-by: Xiaomeng Tong xiam0nd.tong@gmail.com Acked-by: Raphael Gallais-Pou raphael.gallais-pou@foss.st.com Signed-off-by: Philippe Cornu philippe.cornu@foss.st.com Link: https://patchwork.freedesktop.org/patch/msgid/20220327055355.3808-1-xiam0nd.... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com Acked-by: Xie XiuQi xiexiuqi@huawei.com --- drivers/gpu/drm/stm/ltdc.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c index 62488ac14923..089c00a8e7d4 100644 --- a/drivers/gpu/drm/stm/ltdc.c +++ b/drivers/gpu/drm/stm/ltdc.c @@ -527,8 +527,8 @@ static void ltdc_crtc_mode_set_nofb(struct drm_crtc *crtc) struct drm_device *ddev = crtc->dev; struct drm_connector_list_iter iter; struct drm_connector *connector = NULL; - struct drm_encoder *encoder = NULL; - struct drm_bridge *bridge = NULL; + struct drm_encoder *encoder = NULL, *en_iter; + struct drm_bridge *bridge = NULL, *br_iter; struct drm_display_mode *mode = &crtc->state->adjusted_mode; struct videomode vm; u32 hsync, vsync, accum_hbp, accum_vbp, accum_act_w, accum_act_h; @@ -538,15 +538,19 @@ static void ltdc_crtc_mode_set_nofb(struct drm_crtc *crtc) int ret;
/* get encoder from crtc */ - drm_for_each_encoder(encoder, ddev) - if (encoder->crtc == crtc) + drm_for_each_encoder(en_iter, ddev) + if (en_iter->crtc == crtc) { + encoder = en_iter; break; + }
if (encoder) { /* get bridge from encoder */ - list_for_each_entry(bridge, &encoder->bridge_chain, chain_node) - if (bridge->encoder == encoder) + list_for_each_entry(br_iter, &encoder->bridge_chain, chain_node) + if (br_iter->encoder == encoder) { + bridge = br_iter; break; + }
/* Get the connector from encoder */ drm_connector_list_iter_begin(ddev, &iter);