wait_for_completion_timeout return >= 0 but never negative so the check logic looks inconsistent. Further the return value of wait_for_completion_timeout was being passed up the call chain but the x call sites as drm_dp_i2c_do_msg()/drm_dp_dpcd_access() check for < 0 thus timeout was being treated as success case.
<snip> drivers/gpu/drm/drm_dp_helper.c:drm_dp_i2c_do_msg() mutex_lock(&aux->hw_mutex); ret = aux->transfer(aux, msg); mutex_unlock(&aux->hw_mutex); if (ret < 0) { <snip> logic in edp_aux_transfer() seems incorrect as it could return 0 (timeout) but checks of <= 0 to indicate error so the return probably should be -ETIMEDOUT in case wait_for_completion_timeout returns 0 (timeout occurred).
Signed-off-by: Nicholas Mc Guire hofrat@osadl.org ---
This was compile tested with qcom_defconfig + CONFIG_DRM=m (implies CONFIG_DRM_MSM=m)
Patch is against 4.0-rc6 (localversion-next is -next-20150402)
drivers/gpu/drm/msm/edp/edp_aux.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/msm/edp/edp_aux.c b/drivers/gpu/drm/msm/edp/edp_aux.c index 5f5a84f..1d2ccdf 100644 --- a/drivers/gpu/drm/msm/edp/edp_aux.c +++ b/drivers/gpu/drm/msm/edp/edp_aux.c @@ -119,6 +119,7 @@ ssize_t edp_aux_transfer(struct drm_dp_aux *drm_aux, struct drm_dp_aux_msg *msg) { struct edp_aux *aux = to_edp_aux(drm_aux); ssize_t ret; + unsigned long time_left; bool native = msg->request & (DP_AUX_NATIVE_WRITE & DP_AUX_NATIVE_READ); bool read = msg->request & (DP_AUX_I2C_READ & DP_AUX_NATIVE_READ);
@@ -147,15 +148,16 @@ ssize_t edp_aux_transfer(struct drm_dp_aux *drm_aux, struct drm_dp_aux_msg *msg) goto unlock_exit;
DBG("wait_for_completion"); - ret = wait_for_completion_timeout(&aux->msg_comp, 300); - if (ret <= 0) { + time_left = wait_for_completion_timeout(&aux->msg_comp, 300); + if (!time_left) { /* * Clear GO and reset AUX channel * to cancel the current transaction. */ edp_write(aux->base + REG_EDP_AUX_TRANS_CTRL, 0); msm_edp_aux_ctrl(aux, 1); - pr_err("%s: aux timeout, %d\n", __func__, ret); + pr_err("%s: aux timeout, %lu\n", __func__, time_left); + ret = -ETIMEDOUT; goto unlock_exit; } DBG("completion");
The timeout is passed as a constant which makes it HZ dependent because jiffies are expected so it should be converted to jiffies. The actual value is not clear from the code - my best guess is that this should be 300 milliseconds given that other timeouts are in milliseconds based on looking at other drm drivers (e.g. exynos_drm_dsi.c:356 300ms, tegra/dpaux.c:188 250ms) - this needs to be confirmed by someone who knows the details of the driver.
Signed-off-by: Nicholas Mc Guire hofrat@osadl.org ---
This was compile tested with qcom_defconfig + CONFIG_DRM=m (implies CONFIG_DRM_MSM=m)
Patch is against 4.0-rc6 (localversion-next is -next-20150402)
drivers/gpu/drm/msm/edp/edp_aux.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/msm/edp/edp_aux.c b/drivers/gpu/drm/msm/edp/edp_aux.c index 91a1a67..d1b6833 100644 --- a/drivers/gpu/drm/msm/edp/edp_aux.c +++ b/drivers/gpu/drm/msm/edp/edp_aux.c @@ -148,7 +148,8 @@ ssize_t edp_aux_transfer(struct drm_dp_aux *drm_aux, struct drm_dp_aux_msg *msg) goto unlock_exit;
DBG("wait_for_completion"); - time_left = wait_for_completion_timeout(&aux->msg_comp, 300); + time_left = wait_for_completion_timeout(&aux->msg_comp, + msecs_to_jiffies(300)); if (!time_left) { /* * Clear GO and reset AUX channel
wait_for_completion_timeout returns 0 in case of timeout so printing the return value here will always yield 0 and is therefor redundant - dropped.
Signed-off-by: Nicholas Mc Guire hofrat@osadl.org ---
This was compile tested with qcom_defconfig + CONFIG_DRM=m (implies CONFIG_DRM_MSM=m)
Patch is against 4.0-rc6 (localversion-next is -next-20150402)
drivers/gpu/drm/msm/edp/edp_aux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/msm/edp/edp_aux.c b/drivers/gpu/drm/msm/edp/edp_aux.c index d1b6833..645ea07 100644 --- a/drivers/gpu/drm/msm/edp/edp_aux.c +++ b/drivers/gpu/drm/msm/edp/edp_aux.c @@ -157,7 +157,7 @@ ssize_t edp_aux_transfer(struct drm_dp_aux *drm_aux, struct drm_dp_aux_msg *msg) */ edp_write(aux->base + REG_EDP_AUX_TRANS_CTRL, 0); msm_edp_aux_ctrl(aux, 1); - pr_err("%s: aux timeout, %lu\n", __func__, time_left); + pr_err("%s: aux timeout,\n", __func__); ret = -ETIMEDOUT; goto unlock_exit; }
dri-devel@lists.freedesktop.org