Message ID | 20201113222639.18786-1-khsieh@codeaurora.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | drm/msm/dp: fix connect/disconnect handled at ir_hdp | expand |
Hi Kuogee,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on next-20201113]
[cannot apply to drm-intel/for-linux-next drm-exynos/exynos-drm-next tegra-drm/drm/tegra/for-next drm-tip/drm-tip linus/master robclark/msm-next drm/drm-next v5.10-rc3 v5.10-rc2 v5.10-rc1 v5.10-rc3]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]
url: https://github.com/0day-ci/linux/commits/Kuogee-Hsieh/drm-msm-dp-fix-connect-disconnect-handled-at-ir_hdp/20201114-062757
base: 92edc4aef86780a8ad01b092c6d6630bb3cb423d
config: arm64-randconfig-r012-20201113 (attached as .config)
compiler: aarch64-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/0day-ci/linux/commit/7efd7b5dbf73b1ebafbcd74263b814e4b1db4f66
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Kuogee-Hsieh/drm-msm-dp-fix-connect-disconnect-handled-at-ir_hdp/20201114-062757
git checkout 7efd7b5dbf73b1ebafbcd74263b814e4b1db4f66
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=arm64
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
All warnings (new ones prefixed by >>):
drivers/gpu/drm/msm/dp/dp_display.c: In function 'dp_display_handle_irq_hpd':
>> drivers/gpu/drm/msm/dp/dp_display.c:452:6: warning: variable 'sink_request' set but not used [-Wunused-but-set-variable]
452 | u32 sink_request;
| ^~~~~~~~~~~~
vim +/sink_request +452 drivers/gpu/drm/msm/dp/dp_display.c
c943b4948b5848f Chandan Uddaraju 2020-08-27 449
8ede2ecc3e5ee32 Kuogee Hsieh 2020-09-11 450 static int dp_display_handle_irq_hpd(struct dp_display_private *dp)
c943b4948b5848f Chandan Uddaraju 2020-08-27 451 {
8ede2ecc3e5ee32 Kuogee Hsieh 2020-09-11 @452 u32 sink_request;
8ede2ecc3e5ee32 Kuogee Hsieh 2020-09-11 453
8ede2ecc3e5ee32 Kuogee Hsieh 2020-09-11 454 sink_request = dp->link->sink_request;
c943b4948b5848f Chandan Uddaraju 2020-08-27 455
c943b4948b5848f Chandan Uddaraju 2020-08-27 456 dp_ctrl_handle_sink_request(dp->ctrl);
c943b4948b5848f Chandan Uddaraju 2020-08-27 457
8ede2ecc3e5ee32 Kuogee Hsieh 2020-09-11 458 if (dp->link->sink_request & DP_TEST_LINK_VIDEO_PATTERN)
c943b4948b5848f Chandan Uddaraju 2020-08-27 459 dp_display_handle_video_request(dp);
c943b4948b5848f Chandan Uddaraju 2020-08-27 460
c943b4948b5848f Chandan Uddaraju 2020-08-27 461 return 0;
c943b4948b5848f Chandan Uddaraju 2020-08-27 462 }
c943b4948b5848f Chandan Uddaraju 2020-08-27 463
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
Quoting Kuogee Hsieh (2020-11-13 14:26:39) > diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c > index 27e7e27b8b90..4e84f500b721 100644 > --- a/drivers/gpu/drm/msm/dp/dp_display.c > +++ b/drivers/gpu/drm/msm/dp/dp_display.c > @@ -279,13 +279,25 @@ static void dp_display_send_hpd_event(struct msm_dp *dp_display) > drm_helper_hpd_irq_event(connector->dev); > } > > -static int dp_display_send_hpd_notification(struct dp_display_private *dp, > - bool hpd) > + > +static void dp_display_set_encoder_mode(struct dp_display_private *dp) > { > - static bool encoder_mode_set; > struct msm_drm_private *priv = dp->dp_display.drm_dev->dev_private; > struct msm_kms *kms = priv->kms; > + static bool encoder_mode_set; Can this be stored in the dp_display_private structure instead? No singletons please. > + > + if (!encoder_mode_set && dp->dp_display.encoder && > + kms->funcs->set_encoder_mode) { > + kms->funcs->set_encoder_mode(kms, > + dp->dp_display.encoder, false); > > + encoder_mode_set = true; > + } > +} > + > +static int dp_display_send_hpd_notification(struct dp_display_private *dp, > + bool hpd) > +{ > if ((hpd && dp->dp_display.is_connected) || > (!hpd && !dp->dp_display.is_connected)) { > DRM_DEBUG_DP("HPD already %s\n", (hpd ? "on" : "off")); > @@ -491,17 +487,29 @@ static int dp_display_usbpd_attention_cb(struct device *dev) > if (!rc) { > sink_request = dp->link->sink_request; > if (sink_request & DS_PORT_STATUS_CHANGED) { > - /* same as unplugged */ > - hpd->hpd_high = 0; > - dp->hpd_state = ST_DISCONNECT_PENDING; > - dp_add_event(dp, EV_USER_NOTIFICATION, false, 0); > - } > - > - rc = dp_display_handle_irq_hpd(dp); > - > - if (!rc && (sink_request & DS_PORT_STATUS_CHANGED)) { > - hpd->hpd_high = 1; > - dp->hpd_state = ST_CONNECT_PENDING; > + if (dp_display_is_sink_count_zero(dp)) { > + DRM_DEBUG_DP("sink count is zero, nothing to do\n"); > + if (dp->hpd_state != ST_DISCONNECTED) { > + hpd->hpd_high = 0; > + dp->hpd_state = ST_DISCONNECT_PENDING; > + dp_add_event(dp, EV_USER_NOTIFICATION, false, 0); > + } > + rc = -ENOTCONN; > + } else { > + if (dp->hpd_state == ST_DISCONNECTED) { > + hpd->hpd_high = 1; This else and then if can be an else if, right? > + dp->hpd_state = ST_CONNECT_PENDING; > + > + rc = dp_display_process_hpd_high(dp); > + if (rc) { > + hpd->hpd_high = 0; > + dp->hpd_state = ST_DISCONNECTED; > + } > + } > + } > + } else { > + if (!dp_display_is_ds_bridge(dp->panel)) > + rc = dp_display_handle_irq_hpd(dp); > } > } >
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 27e7e27b8b90..4e84f500b721 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -279,13 +279,25 @@ static void dp_display_send_hpd_event(struct msm_dp *dp_display) drm_helper_hpd_irq_event(connector->dev); } -static int dp_display_send_hpd_notification(struct dp_display_private *dp, - bool hpd) + +static void dp_display_set_encoder_mode(struct dp_display_private *dp) { - static bool encoder_mode_set; struct msm_drm_private *priv = dp->dp_display.drm_dev->dev_private; struct msm_kms *kms = priv->kms; + static bool encoder_mode_set; + + if (!encoder_mode_set && dp->dp_display.encoder && + kms->funcs->set_encoder_mode) { + kms->funcs->set_encoder_mode(kms, + dp->dp_display.encoder, false); + encoder_mode_set = true; + } +} + +static int dp_display_send_hpd_notification(struct dp_display_private *dp, + bool hpd) +{ if ((hpd && dp->dp_display.is_connected) || (!hpd && !dp->dp_display.is_connected)) { DRM_DEBUG_DP("HPD already %s\n", (hpd ? "on" : "off")); @@ -298,15 +310,6 @@ static int dp_display_send_hpd_notification(struct dp_display_private *dp, dp->dp_display.is_connected = hpd; - if (dp->dp_display.is_connected && dp->dp_display.encoder - && !encoder_mode_set - && kms->funcs->set_encoder_mode) { - kms->funcs->set_encoder_mode(kms, - dp->dp_display.encoder, false); - DRM_DEBUG_DP("set_encoder_mode() Completed\n"); - encoder_mode_set = true; - } - dp_display_send_hpd_event(&dp->dp_display); return 0; @@ -359,6 +362,8 @@ static void dp_display_host_init(struct dp_display_private *dp) if (dp->usbpd->orientation == ORIENTATION_CC2) flip = true; + dp_display_set_encoder_mode(dp); + dp_power_init(dp->power, flip); dp_ctrl_host_init(dp->ctrl, flip); dp_aux_init(dp->aux); @@ -448,15 +453,6 @@ static int dp_display_handle_irq_hpd(struct dp_display_private *dp) sink_request = dp->link->sink_request; - if (sink_request & DS_PORT_STATUS_CHANGED) { - if (dp_display_is_sink_count_zero(dp)) { - DRM_DEBUG_DP("sink count is zero, nothing to do\n"); - return -ENOTCONN; - } - - return dp_display_process_hpd_high(dp); - } - dp_ctrl_handle_sink_request(dp->ctrl); if (dp->link->sink_request & DP_TEST_LINK_VIDEO_PATTERN) @@ -491,17 +487,29 @@ static int dp_display_usbpd_attention_cb(struct device *dev) if (!rc) { sink_request = dp->link->sink_request; if (sink_request & DS_PORT_STATUS_CHANGED) { - /* same as unplugged */ - hpd->hpd_high = 0; - dp->hpd_state = ST_DISCONNECT_PENDING; - dp_add_event(dp, EV_USER_NOTIFICATION, false, 0); - } - - rc = dp_display_handle_irq_hpd(dp); - - if (!rc && (sink_request & DS_PORT_STATUS_CHANGED)) { - hpd->hpd_high = 1; - dp->hpd_state = ST_CONNECT_PENDING; + if (dp_display_is_sink_count_zero(dp)) { + DRM_DEBUG_DP("sink count is zero, nothing to do\n"); + if (dp->hpd_state != ST_DISCONNECTED) { + hpd->hpd_high = 0; + dp->hpd_state = ST_DISCONNECT_PENDING; + dp_add_event(dp, EV_USER_NOTIFICATION, false, 0); + } + rc = -ENOTCONN; + } else { + if (dp->hpd_state == ST_DISCONNECTED) { + hpd->hpd_high = 1; + dp->hpd_state = ST_CONNECT_PENDING; + + rc = dp_display_process_hpd_high(dp); + if (rc) { + hpd->hpd_high = 0; + dp->hpd_state = ST_DISCONNECTED; + } + } + } + } else { + if (!dp_display_is_ds_bridge(dp->panel)) + rc = dp_display_handle_irq_hpd(dp); } } @@ -661,6 +669,7 @@ static int dp_disconnect_pending_timeout(struct dp_display_private *dp, u32 data static int dp_irq_hpd_handle(struct dp_display_private *dp, u32 data) { u32 state; + int ret; mutex_lock(&dp->event_mutex); @@ -671,7 +680,10 @@ static int dp_irq_hpd_handle(struct dp_display_private *dp, u32 data) return 0; } - dp_display_usbpd_attention_cb(&dp->pdev->dev); + ret = dp_display_usbpd_attention_cb(&dp->pdev->dev); + if (ret == -ECONNRESET) { /* cable unplugged */ + dp->core_initialized = false; + } mutex_unlock(&dp->event_mutex);
Some usb type-c dongle use irq_hpd request to perform device connect and disconnect. This patch add handling of both connection and disconnection are based on hpd_state and sink_count. Fixes: 6c6e8b2e04d5 ("drm/msm/dp: promote irq_hpd handle to handle link training correctly") Signed-off-by: Kuogee Hsieh <khsieh@codeaurora.org> --- drivers/gpu/drm/msm/dp/dp_display.c | 78 +++++++++++++++++------------ 1 file changed, 45 insertions(+), 33 deletions(-) base-commit: 6c6e8b2e04d537f42b5ebb8b8b0b31a39b44ccf4