disp: msm: dp: fix aux error handling

If an aux transaction fails at its lowest level, there is a builtin
retry mechanism before erroring out. Currently an error message is
printed after each failed attempt even though the aux transaction
might succeed on retry.

This change switches the alert level to warning on these attempts
and makes sure an error message is printed if the transfer errors
out after retries.

Change-Id: I47fb27fe0aa15eb5e2400c4338f9b9c59439983f
Signed-off-by: Rajkumar Subbiah <quic_rsubbia@quicinc.com>
This commit is contained in:
Rajkumar Subbiah
2023-04-06 13:27:36 -07:00
parent 36ba8cc716
commit efbcec2fb0
4 changed files with 68 additions and 32 deletions

View File

@@ -35,6 +35,14 @@
DP_WARN_V(fmt, ##__VA_ARGS__); \ DP_WARN_V(fmt, ##__VA_ARGS__); \
} while (0) } while (0)
#define DP_AUX_WARN_RATELIMITED(dp_aux, fmt, ...) \
do { \
if (dp_aux) \
ipc_log_string(dp_aux->ipc_log_context, "[w][%-4d]"fmt,\
current->pid, ##__VA_ARGS__); \
DP_WARN_RATELIMITED_V(fmt, ##__VA_ARGS__); \
} while (0)
#define DP_AUX_ERR(dp_aux, fmt, ...) \ #define DP_AUX_ERR(dp_aux, fmt, ...) \
do { \ do { \
if (dp_aux) \ if (dp_aux) \
@@ -210,26 +218,32 @@ static int dp_aux_cmd_fifo_tx(struct dp_aux_private *aux,
u32 ret = 0, len = 0, timeout; u32 ret = 0, len = 0, timeout;
int const aux_timeout_ms = HZ/4; int const aux_timeout_ms = HZ/4;
struct dp_aux *dp_aux = &aux->dp_aux; struct dp_aux *dp_aux = &aux->dp_aux;
char prefix[64];
snprintf(prefix, sizeof(prefix), "%s %s %4xh(%2zu): ",
(msg->request & DP_AUX_I2C_MOT) ? "I2C" : "NAT",
(msg->request & DP_AUX_I2C_READ) ? "RD" : "WR",
msg->address, msg->size);
reinit_completion(&aux->comp); reinit_completion(&aux->comp);
len = dp_aux_write(aux, msg); len = dp_aux_write(aux, msg);
if (len == 0) { if (len == 0) {
DP_AUX_ERR(dp_aux, "DP AUX write failed\n"); DP_AUX_ERR(dp_aux, "DP AUX write failed: %s\n", prefix);
return -EINVAL; return -EINVAL;
} }
timeout = wait_for_completion_timeout(&aux->comp, aux_timeout_ms); timeout = wait_for_completion_timeout(&aux->comp, aux_timeout_ms);
if (!timeout) { if (!timeout) {
DP_AUX_ERR(dp_aux, "aux %s timeout\n", (aux->read ? "read" : "write")); DP_AUX_WARN_RATELIMITED(dp_aux, "aux timeout during [%s]\n", prefix);
return -ETIMEDOUT; return -ETIMEDOUT;
} }
if (aux->aux_error_num == DP_AUX_ERR_NONE) { if (aux->aux_error_num == DP_AUX_ERR_NONE) {
ret = len; ret = len;
} else { } else {
DP_AUX_ERR_RATELIMITED(dp_aux, "aux err: %s\n", DP_AUX_WARN_RATELIMITED(dp_aux, "aux err [%s] during [%s]\n",
dp_aux_get_error(aux->aux_error_num)); dp_aux_get_error(aux->aux_error_num), prefix);
ret = -EINVAL; ret = -EINVAL;
} }

View File

@@ -69,6 +69,10 @@
pr_warn("[drm:%s][msm-dp-warn][%-4d]"fmt, __func__, \ pr_warn("[drm:%s][msm-dp-warn][%-4d]"fmt, __func__, \
current->pid, ##__VA_ARGS__) current->pid, ##__VA_ARGS__)
#define DP_WARN_RATELIMITED_V(fmt, ...) \
pr_warn_ratelimited("[drm:%s][msm-dp-warn][%-4d]"fmt, __func__, \
current->pid, ##__VA_ARGS__)
#define DP_ERR_V(fmt, ...) \ #define DP_ERR_V(fmt, ...) \
pr_err("[drm:%s][msm-dp-err][%-4d]"fmt, __func__, \ pr_err("[drm:%s][msm-dp-err][%-4d]"fmt, __func__, \
current->pid, ##__VA_ARGS__) current->pid, ##__VA_ARGS__)

View File

@@ -1512,13 +1512,15 @@ static u32 dp_link_get_test_bits_depth(struct dp_link *dp_link, u32 bpp)
int dp_link_probe(struct drm_dp_aux *aux, struct drm_dp_link *link) int dp_link_probe(struct drm_dp_aux *aux, struct drm_dp_link *link)
{ {
u8 values[3]; u8 values[3];
int err; int ret;
memset(link, 0, sizeof(*link)); memset(link, 0, sizeof(*link));
err = drm_dp_dpcd_read(aux, DP_DPCD_REV, values, sizeof(values)); ret = drm_dp_dpcd_read(aux, DP_DPCD_REV, values, sizeof(values));
if (err < 0) if (ret < 3) {
return err; DP_ERR("failed to probe link, ret:%d\n", ret);
ret = -EIO;
}
link->revision = values[0]; link->revision = values[0];
link->rate = drm_dp_bw_code_to_link_rate(values[1]); link->rate = drm_dp_bw_code_to_link_rate(values[1]);
@@ -1540,22 +1542,26 @@ int dp_link_probe(struct drm_dp_aux *aux, struct drm_dp_link *link)
int dp_link_power_up(struct drm_dp_aux *aux, struct drm_dp_link *link) int dp_link_power_up(struct drm_dp_aux *aux, struct drm_dp_link *link)
{ {
u8 value; u8 value;
int err; int ret;
/* DP_SET_POWER register is only available on DPCD v1.1 and later */ /* DP_SET_POWER register is only available on DPCD v1.1 and later */
if (link->revision < 0x11) if (link->revision < 0x11)
return 0; return 0;
err = drm_dp_dpcd_readb(aux, DP_SET_POWER, &value); ret = drm_dp_dpcd_readb(aux, DP_SET_POWER, &value);
if (err < 0) if (ret != 1) {
return err; DP_ERR("failed to read sink power when powering up, ret:%d\n", ret);
return -EIO;
}
value &= ~DP_SET_POWER_MASK; value &= ~DP_SET_POWER_MASK;
value |= DP_SET_POWER_D0; value |= DP_SET_POWER_D0;
err = drm_dp_dpcd_writeb(aux, DP_SET_POWER, value); ret = drm_dp_dpcd_writeb(aux, DP_SET_POWER, value);
if (err < 0) if (ret != 1) {
return err; DP_ERR("failed to power up[0x%x] sink, ret:%d\n", value, ret);
return -EIO;
}
/* /*
* According to the DP 1.1 specification, a "Sink Device must exit the * According to the DP 1.1 specification, a "Sink Device must exit the
@@ -1577,22 +1583,26 @@ int dp_link_power_up(struct drm_dp_aux *aux, struct drm_dp_link *link)
int dp_link_power_down(struct drm_dp_aux *aux, struct drm_dp_link *link) int dp_link_power_down(struct drm_dp_aux *aux, struct drm_dp_link *link)
{ {
u8 value; u8 value;
int err; int ret;
/* DP_SET_POWER register is only available on DPCD v1.1 and later */ /* DP_SET_POWER register is only available on DPCD v1.1 and later */
if (link->revision < 0x11) if (link->revision < 0x11)
return 0; return 0;
err = drm_dp_dpcd_readb(aux, DP_SET_POWER, &value); ret = drm_dp_dpcd_readb(aux, DP_SET_POWER, &value);
if (err < 0) if (ret != 1) {
return err; DP_ERR("failed to read sink power when powering down, ret:%d\n", ret);
return -EIO;
}
value &= ~DP_SET_POWER_MASK; value &= ~DP_SET_POWER_MASK;
value |= DP_SET_POWER_D3; value |= DP_SET_POWER_D3;
err = drm_dp_dpcd_writeb(aux, DP_SET_POWER, value); ret = drm_dp_dpcd_writeb(aux, DP_SET_POWER, value);
if (err < 0) if (ret != 1) {
return err; DP_ERR("failed to power down[0x%x] sink, ret:%d\n", value, ret);
return -EIO;
}
return 0; return 0;
} }
@@ -1607,7 +1617,7 @@ int dp_link_power_down(struct drm_dp_aux *aux, struct drm_dp_link *link)
int dp_link_configure(struct drm_dp_aux *aux, struct drm_dp_link *link) int dp_link_configure(struct drm_dp_aux *aux, struct drm_dp_link *link)
{ {
u8 values[2]; u8 values[2];
int err; int ret;
values[0] = drm_dp_link_rate_to_bw_code(link->rate); values[0] = drm_dp_link_rate_to_bw_code(link->rate);
values[1] = link->num_lanes; values[1] = link->num_lanes;
@@ -1615,9 +1625,11 @@ int dp_link_configure(struct drm_dp_aux *aux, struct drm_dp_link *link)
if (link->capabilities & DP_LINK_CAP_ENHANCED_FRAMING) if (link->capabilities & DP_LINK_CAP_ENHANCED_FRAMING)
values[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; values[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
err = drm_dp_dpcd_write(aux, DP_LINK_BW_SET, values, sizeof(values)); ret = drm_dp_dpcd_write(aux, DP_LINK_BW_SET, values, sizeof(values));
if (err < 0) if (ret != 2) {
return err; DP_ERR("failed to configure link, ret:%d\n", ret);
return -EIO;
}
return 0; return 0;
} }

View File

@@ -3091,8 +3091,10 @@ int dp_panel_get_sink_crc(struct dp_panel *dp_panel, u16 *crc)
* per component (RGB or CrYCb). * per component (RGB or CrYCb).
*/ */
rc = drm_dp_dpcd_read(drm_aux, DP_TEST_CRC_R_CR, crc_bytes, 6); rc = drm_dp_dpcd_read(drm_aux, DP_TEST_CRC_R_CR, crc_bytes, 6);
if (rc < 0) if (rc != 6) {
return rc; DP_ERR("failed to read sink CRC, ret:%d\n", rc);
return -EIO;
}
rc = 0; rc = 0;
crc[0] = crc_bytes[0] | crc_bytes[1] << 8; crc[0] = crc_bytes[0] | crc_bytes[1] << 8;
@@ -3115,12 +3117,16 @@ int dp_panel_sink_crc_enable(struct dp_panel *dp_panel, bool enable)
if (dp_panel->link_info.capabilities & DP_LINK_CAP_CRC) { if (dp_panel->link_info.capabilities & DP_LINK_CAP_CRC) {
ret = drm_dp_dpcd_readb(drm_aux, DP_TEST_SINK, &buf); ret = drm_dp_dpcd_readb(drm_aux, DP_TEST_SINK, &buf);
if (ret < 0) if (ret != 1) {
return ret; DP_ERR("failed to read CRC cap, ret:%d\n", ret);
return -EIO;
}
ret = drm_dp_dpcd_writeb(drm_aux, DP_TEST_SINK, buf | DP_TEST_SINK_START); ret = drm_dp_dpcd_writeb(drm_aux, DP_TEST_SINK, buf | DP_TEST_SINK_START);
if (ret < 0) if (ret != 1) {
return ret; DP_ERR("failed to enable Sink CRC, ret:%d\n", ret);
return -EIO;
}
drm_dp_dpcd_readb(drm_aux, DP_TEST_SINK, &buf); drm_dp_dpcd_readb(drm_aux, DP_TEST_SINK, &buf);
} }