Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/msm/dp: Handle aux timeouts, nacks, defers

Let's look at the irq status bits after a transfer and see if we got a
nack or a defer or a timeout, instead of telling drm layers that
everything was fine, while still printing an error message. I wasn't
sure about NACK+DEFER so I lumped all those various errors along with a
nack so that the drm core can figure out that things are just not going
well. The important thing is that we're now returning -ETIMEDOUT when
the message times out and nacks for bad addresses.

Cc: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Cc: Abhinav Kumar <abhinavk@codeaurora.org>
Cc: Kuogee Hsieh <khsieh@codeaurora.org>
Cc: aravindh@codeaurora.org
Cc: Sean Paul <sean@poorly.run>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
Reviewed-by: Kuogee Hsieh <khsieh@codeaurora.org>
Link: https://lore.kernel.org/r/20210507212505.1224111-4-swboyd@chromium.org
Signed-off-by: Rob Clark <robdclark@chromium.org>

authored by

Stephen Boyd and committed by
Rob Clark
e305f678 47327fdd

+61 -87
+61 -79
drivers/gpu/drm/msm/dp/dp_aux.c
··· 9 9 #include "dp_reg.h" 10 10 #include "dp_aux.h" 11 11 12 - #define DP_AUX_ENUM_STR(x) #x 12 + enum msm_dp_aux_err { 13 + DP_AUX_ERR_NONE, 14 + DP_AUX_ERR_ADDR, 15 + DP_AUX_ERR_TOUT, 16 + DP_AUX_ERR_NACK, 17 + DP_AUX_ERR_DEFER, 18 + DP_AUX_ERR_NACK_DEFER, 19 + DP_AUX_ERR_PHY, 20 + }; 13 21 14 22 struct dp_aux_private { 15 23 struct device *dev; ··· 26 18 struct mutex mutex; 27 19 struct completion comp; 28 20 29 - u32 aux_error_num; 21 + enum msm_dp_aux_err aux_error_num; 30 22 u32 retry_cnt; 31 23 bool cmd_busy; 32 24 bool native; ··· 41 33 42 34 #define MAX_AUX_RETRIES 5 43 35 44 - static const char *dp_aux_get_error(u32 aux_error) 45 - { 46 - switch (aux_error) { 47 - case DP_AUX_ERR_NONE: 48 - return DP_AUX_ENUM_STR(DP_AUX_ERR_NONE); 49 - case DP_AUX_ERR_ADDR: 50 - return DP_AUX_ENUM_STR(DP_AUX_ERR_ADDR); 51 - case DP_AUX_ERR_TOUT: 52 - return DP_AUX_ENUM_STR(DP_AUX_ERR_TOUT); 53 - case DP_AUX_ERR_NACK: 54 - return DP_AUX_ENUM_STR(DP_AUX_ERR_NACK); 55 - case DP_AUX_ERR_DEFER: 56 - return DP_AUX_ENUM_STR(DP_AUX_ERR_DEFER); 57 - case DP_AUX_ERR_NACK_DEFER: 58 - return DP_AUX_ENUM_STR(DP_AUX_ERR_NACK_DEFER); 59 - default: 60 - return "unknown"; 61 - } 62 - } 63 - 64 - static u32 dp_aux_write(struct dp_aux_private *aux, 36 + static ssize_t dp_aux_write(struct dp_aux_private *aux, 65 37 struct drm_dp_aux_msg *msg) 66 38 { 67 - u32 data[4], reg, len; 39 + u8 data[4]; 40 + u32 reg; 41 + ssize_t len; 68 42 u8 *msgdata = msg->buffer; 69 43 int const AUX_CMD_FIFO_LEN = 128; 70 44 int i = 0; 71 45 72 46 if (aux->read) 73 - len = 4; 47 + len = 0; 74 48 else 75 - len = msg->size + 4; 49 + len = msg->size; 76 50 77 51 /* 78 52 * cmd fifo only has depth of 144 bytes 79 53 * limit buf length to 128 bytes here 80 54 */ 81 - if (len > AUX_CMD_FIFO_LEN) { 55 + if (len > AUX_CMD_FIFO_LEN - 4) { 82 56 DRM_ERROR("buf size greater than allowed size of 128 bytes\n"); 83 - return 0; 57 + return -EINVAL; 84 58 } 85 59 86 60 /* Pack cmd and write to HW */ 87 - data[0] = (msg->address >> 16) & 0xf; /* addr[19:16] */ 61 + data[0] = (msg->address >> 16) & 0xf; /* addr[19:16] */ 88 62 if (aux->read) 89 - data[0] |= BIT(4); /* R/W */ 63 + data[0] |= BIT(4); /* R/W */ 90 64 91 - data[1] = (msg->address >> 8) & 0xff; /* addr[15:8] */ 92 - data[2] = msg->address & 0xff; /* addr[7:0] */ 93 - data[3] = (msg->size - 1) & 0xff; /* len[7:0] */ 65 + data[1] = msg->address >> 8; /* addr[15:8] */ 66 + data[2] = msg->address; /* addr[7:0] */ 67 + data[3] = msg->size - 1; /* len[7:0] */ 94 68 95 - for (i = 0; i < len; i++) { 69 + for (i = 0; i < len + 4; i++) { 96 70 reg = (i < 4) ? data[i] : msgdata[i - 4]; 71 + reg <<= DP_AUX_DATA_OFFSET; 72 + reg &= DP_AUX_DATA_MASK; 73 + reg |= DP_AUX_DATA_WRITE; 97 74 /* index = 0, write */ 98 - reg = (((reg) << DP_AUX_DATA_OFFSET) 99 - & DP_AUX_DATA_MASK) | DP_AUX_DATA_WRITE; 100 75 if (i == 0) 101 76 reg |= DP_AUX_DATA_INDEX_WRITE; 102 77 aux->catalog->aux_data = reg; ··· 107 116 return len; 108 117 } 109 118 110 - static int dp_aux_cmd_fifo_tx(struct dp_aux_private *aux, 119 + static ssize_t dp_aux_cmd_fifo_tx(struct dp_aux_private *aux, 111 120 struct drm_dp_aux_msg *msg) 112 121 { 113 - u32 ret, len, timeout; 114 - int aux_timeout_ms = HZ/4; 122 + ssize_t ret; 123 + unsigned long time_left; 115 124 116 125 reinit_completion(&aux->comp); 117 126 118 - len = dp_aux_write(aux, msg); 119 - if (len == 0) { 120 - DRM_ERROR("DP AUX write failed\n"); 121 - return -EINVAL; 122 - } 127 + ret = dp_aux_write(aux, msg); 128 + if (ret < 0) 129 + return ret; 123 130 124 - timeout = wait_for_completion_timeout(&aux->comp, aux_timeout_ms); 125 - if (!timeout) { 126 - DRM_ERROR("aux %s timeout\n", (aux->read ? "read" : "write")); 131 + time_left = wait_for_completion_timeout(&aux->comp, 132 + msecs_to_jiffies(250)); 133 + if (!time_left) 127 134 return -ETIMEDOUT; 128 - } 129 - 130 - if (aux->aux_error_num == DP_AUX_ERR_NONE) { 131 - ret = len; 132 - } else { 133 - DRM_ERROR_RATELIMITED("aux err: %s\n", 134 - dp_aux_get_error(aux->aux_error_num)); 135 - 136 - ret = -EINVAL; 137 - } 138 135 139 136 return ret; 140 137 } 141 138 142 - static void dp_aux_cmd_fifo_rx(struct dp_aux_private *aux, 139 + static ssize_t dp_aux_cmd_fifo_rx(struct dp_aux_private *aux, 143 140 struct drm_dp_aux_msg *msg) 144 141 { 145 142 u32 data; ··· 154 175 155 176 actual_i = (data >> DP_AUX_DATA_INDEX_OFFSET) & 0xFF; 156 177 if (i != actual_i) 157 - DRM_ERROR("Index mismatch: expected %d, found %d\n", 158 - i, actual_i); 178 + break; 159 179 } 180 + 181 + return i; 160 182 } 161 183 162 184 static void dp_aux_native_handler(struct dp_aux_private *aux, u32 isr) ··· 347 367 } 348 368 349 369 ret = dp_aux_cmd_fifo_tx(aux, msg); 350 - 351 370 if (ret < 0) { 352 371 if (aux->native) { 353 372 aux->retry_cnt++; 354 373 if (!(aux->retry_cnt % MAX_AUX_RETRIES)) 355 374 dp_catalog_aux_update_cfg(aux->catalog); 356 375 } 357 - usleep_range(400, 500); /* at least 400us to next try */ 358 - goto unlock_exit; 359 - } 360 - 361 - if (aux->aux_error_num == DP_AUX_ERR_NONE) { 362 - if (aux->read) 363 - dp_aux_cmd_fifo_rx(aux, msg); 364 - 365 - msg->reply = aux->native ? 366 - DP_AUX_NATIVE_REPLY_ACK : DP_AUX_I2C_REPLY_ACK; 367 376 } else { 368 - /* Reply defer to retry */ 369 - msg->reply = aux->native ? 370 - DP_AUX_NATIVE_REPLY_DEFER : DP_AUX_I2C_REPLY_DEFER; 377 + aux->retry_cnt = 0; 378 + switch (aux->aux_error_num) { 379 + case DP_AUX_ERR_NONE: 380 + if (aux->read) 381 + ret = dp_aux_cmd_fifo_rx(aux, msg); 382 + msg->reply = aux->native ? DP_AUX_NATIVE_REPLY_ACK : DP_AUX_I2C_REPLY_ACK; 383 + break; 384 + case DP_AUX_ERR_DEFER: 385 + msg->reply = aux->native ? DP_AUX_NATIVE_REPLY_DEFER : DP_AUX_I2C_REPLY_DEFER; 386 + break; 387 + case DP_AUX_ERR_PHY: 388 + case DP_AUX_ERR_ADDR: 389 + case DP_AUX_ERR_NACK: 390 + case DP_AUX_ERR_NACK_DEFER: 391 + msg->reply = aux->native ? DP_AUX_NATIVE_REPLY_NACK : DP_AUX_I2C_REPLY_NACK; 392 + break; 393 + case DP_AUX_ERR_TOUT: 394 + ret = -ETIMEDOUT; 395 + break; 396 + } 371 397 } 372 398 373 - /* Return requested size for success or retry */ 374 - ret = msg->size; 375 - aux->retry_cnt = 0; 376 - 377 - unlock_exit: 378 399 aux->cmd_busy = false; 379 400 mutex_unlock(&aux->mutex); 401 + 380 402 return ret; 381 403 } 382 404
-8
drivers/gpu/drm/msm/dp/dp_aux.h
··· 9 9 #include "dp_catalog.h" 10 10 #include <drm/drm_dp_helper.h> 11 11 12 - #define DP_AUX_ERR_NONE 0 13 - #define DP_AUX_ERR_ADDR -1 14 - #define DP_AUX_ERR_TOUT -2 15 - #define DP_AUX_ERR_NACK -3 16 - #define DP_AUX_ERR_DEFER -4 17 - #define DP_AUX_ERR_NACK_DEFER -5 18 - #define DP_AUX_ERR_PHY -6 19 - 20 12 int dp_aux_register(struct drm_dp_aux *dp_aux); 21 13 void dp_aux_unregister(struct drm_dp_aux *dp_aux); 22 14 void dp_aux_isr(struct drm_dp_aux *dp_aux);