Message ID | 20230619082715.922094-1-arun.r.murthy@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [PATCHv4] drm/i915/display/dp: On AUX xfer timeout restart freshly | expand |
Hi Arun, kernel test robot noticed the following build warnings: [auto build test WARNING on drm-tip/drm-tip] url: https://github.com/intel-lab-lkp/linux/commits/Arun-R-Murthy/drm-i915-display-dp-On-AUX-xfer-timeout-restart-freshly/20230619-163622 base: git://anongit.freedesktop.org/drm/drm-tip drm-tip patch link: https://lore.kernel.org/r/20230619082715.922094-1-arun.r.murthy%40intel.com patch subject: [Intel-gfx] [PATCHv4] drm/i915/display/dp: On AUX xfer timeout restart freshly config: x86_64-rhel-8.3-rust (https://download.01.org/0day-ci/archive/20230619/202306191845.yMTzbDgG-lkp@intel.com/config) compiler: clang version 15.0.7 (https://github.com/llvm/llvm-project.git 8dfdcc7b7bf66834a761bd8de445840ef68e4d1a) reproduce: (https://download.01.org/0day-ci/archive/20230619/202306191845.yMTzbDgG-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202306191845.yMTzbDgG-lkp@intel.com/ All warnings (new ones prefixed by >>): >> drivers/gpu/drm/i915/display/intel_dp_aux.c:284:12: warning: variable 'aux_clock_divider' is uninitialized when used here [-Wuninitialized] aux_clock_divider); ^~~~~~~~~~~~~~~~~ drivers/gpu/drm/i915/display/intel_dp_aux.c:222:23: note: initialize the variable 'aux_clock_divider' to silence this warning u32 aux_clock_divider; ^ = 0 1 warning generated. vim +/aux_clock_divider +284 drivers/gpu/drm/i915/display/intel_dp_aux.c 209 210 static int 211 intel_dp_aux_xfer(struct intel_dp *intel_dp, 212 const u8 *send, int send_bytes, 213 u8 *recv, int recv_size, 214 u32 aux_send_ctl_flags) 215 { 216 struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); 217 struct drm_i915_private *i915 = 218 to_i915(dig_port->base.base.dev); 219 enum phy phy = intel_port_to_phy(i915, dig_port->base.port); 220 bool is_tc_port = intel_phy_is_tc(i915, phy); 221 i915_reg_t ch_ctl, ch_data[5]; 222 u32 aux_clock_divider; 223 enum intel_display_power_domain aux_domain; 224 intel_wakeref_t aux_wakeref; 225 intel_wakeref_t pps_wakeref; 226 int i, ret, recv_bytes; 227 int try, clock = 0; 228 u32 status; 229 u32 send_ctl; 230 bool vdd; 231 232 ch_ctl = intel_dp->aux_ch_ctl_reg(intel_dp); 233 for (i = 0; i < ARRAY_SIZE(ch_data); i++) 234 ch_data[i] = intel_dp->aux_ch_data_reg(intel_dp, i); 235 236 if (is_tc_port) { 237 intel_tc_port_lock(dig_port); 238 /* 239 * Abort transfers on a disconnected port as required by 240 * DP 1.4a link CTS 4.2.1.5, also avoiding the long AUX 241 * timeouts that would otherwise happen. 242 * TODO: abort the transfer on non-TC ports as well. 243 */ 244 if (!intel_tc_port_connected_locked(&dig_port->base)) { 245 ret = -ENXIO; 246 goto out_unlock; 247 } 248 } 249 250 aux_domain = intel_aux_power_domain(dig_port); 251 252 aux_wakeref = intel_display_power_get(i915, aux_domain); 253 pps_wakeref = intel_pps_lock(intel_dp); 254 255 /* 256 * We will be called with VDD already enabled for dpcd/edid/oui reads. 257 * In such cases we want to leave VDD enabled and it's up to upper layers 258 * to turn it off. But for eg. i2c-dev access we need to turn it on/off 259 * ourselves. 260 */ 261 vdd = intel_pps_vdd_on_unlocked(intel_dp); 262 263 /* 264 * dp aux is extremely sensitive to irq latency, hence request the 265 * lowest possible wakeup latency and so prevent the cpu from going into 266 * deep sleep states. 267 */ 268 cpu_latency_qos_update_request(&intel_dp->pm_qos, 0); 269 270 intel_pps_check_power_unlocked(intel_dp); 271 272 /* 273 * FIXME PSR should be disabled here to prevent 274 * it using the same AUX CH simultaneously 275 */ 276 277 /* Only 5 data registers! */ 278 if (drm_WARN_ON(&i915->drm, send_bytes > 20 || recv_size > 20)) { 279 ret = -E2BIG; 280 goto out; 281 } 282 send_ctl = intel_dp->get_aux_send_ctl(intel_dp, 283 send_bytes, > 284 aux_clock_divider); 285 send_ctl |= aux_send_ctl_flags; 286 287 while ((aux_clock_divider = intel_dp->get_aux_clock_divider(intel_dp, clock++))) { 288 /* Re-visit : Must try at least 3 times according to DP spec */ 289 for (try = 0; try < 5; try++) { 290 /* Try to wait for any previous AUX channel activity */ 291 status = intel_dp_aux_wait_done(intel_dp); 292 /* just trace the final value */ 293 trace_i915_reg_rw(false, ch_ctl, status, sizeof(status), true); 294 295 if (status & DP_AUX_CH_CTL_SEND_BUSY) { 296 drm_WARN(&i915->drm, 1, 297 "%s: not started, previous Tx still in process (status 0x%08x)\n", 298 intel_dp->aux.name, status); 299 intel_dp->aux_busy_last_status = status; 300 if (try > 3) { 301 ret = -EBUSY; 302 goto out; 303 } else 304 continue; 305 } 306 307 /* Load the send data into the aux channel data registers */ 308 for (i = 0; i < send_bytes; i += 4) 309 intel_de_write(i915, ch_data[i >> 2], 310 intel_dp_aux_pack(send + i, 311 send_bytes - i)); 312 313 /* Send the command and wait for it to complete */ 314 intel_de_write(i915, ch_ctl, send_ctl); 315 316 /* TODO: if typeC then 4.2ms else 800us. For DG2 add 1.5ms for both cases */ 317 status = intel_dp_aux_wait_done(intel_dp); 318 319 /* Clear done status and any errors */ 320 intel_de_write(i915, ch_ctl, 321 status | DP_AUX_CH_CTL_DONE | 322 DP_AUX_CH_CTL_TIME_OUT_ERROR | 323 DP_AUX_CH_CTL_RECEIVE_ERROR); 324 325 /* 326 * DP CTS 1.2 Core Rev 1.1, 4.2.1.1 & 4.2.1.2 327 * 400us delay required for errors and timeouts 328 * Timeout errors from the HW already meet this 329 * requirement so skip to next iteration 330 */ 331 if (status & (DP_AUX_CH_CTL_TIME_OUT_ERROR | 332 DP_AUX_CH_CTL_SEND_BUSY)) 333 continue; 334 335 if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) { 336 usleep_range(400, 500); 337 continue; 338 } 339 if (status & DP_AUX_CH_CTL_DONE) 340 goto done; 341 } 342 } 343 344 if ((status & DP_AUX_CH_CTL_DONE) == 0) { 345 drm_err(&i915->drm, "%s: not done (status 0x%08x)\n", 346 intel_dp->aux.name, status); 347 ret = -EBUSY; 348 goto out; 349 } 350 351 done: 352 /* 353 * Check for timeout or receive error. Timeouts occur when the sink is 354 * not connected. 355 */ 356 if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) { 357 drm_err(&i915->drm, "%s: receive error (status 0x%08x)\n", 358 intel_dp->aux.name, status); 359 ret = -EIO; 360 goto out; 361 } 362 363 /* 364 * Timeouts occur when the device isn't connected, so they're "normal" 365 * -- don't fill the kernel log with these 366 */ 367 if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR) { 368 drm_dbg_kms(&i915->drm, "%s: timeout (status 0x%08x)\n", 369 intel_dp->aux.name, status); 370 ret = -ETIMEDOUT; 371 goto out; 372 } 373 374 /* Unload any bytes sent back from the other side */ 375 recv_bytes = REG_FIELD_GET(DP_AUX_CH_CTL_MESSAGE_SIZE_MASK, status); 376 377 /* 378 * By BSpec: "Message sizes of 0 or >20 are not allowed." 379 * We have no idea of what happened so we return -EBUSY so 380 * drm layer takes care for the necessary retries. 381 */ 382 if (recv_bytes == 0 || recv_bytes > 20) { 383 drm_dbg_kms(&i915->drm, 384 "%s: Forbidden recv_bytes = %d on aux transaction\n", 385 intel_dp->aux.name, recv_bytes); 386 ret = -EBUSY; 387 goto out; 388 } 389 390 if (recv_bytes > recv_size) 391 recv_bytes = recv_size; 392 393 for (i = 0; i < recv_bytes; i += 4) 394 intel_dp_aux_unpack(intel_de_read(i915, ch_data[i >> 2]), 395 recv + i, recv_bytes - i); 396 397 ret = recv_bytes; 398 out: 399 cpu_latency_qos_update_request(&intel_dp->pm_qos, PM_QOS_DEFAULT_VALUE); 400 401 if (vdd) 402 intel_pps_vdd_off_unlocked(intel_dp, false); 403 404 intel_pps_unlock(intel_dp, pps_wakeref); 405 intel_display_power_put_async(i915, aux_domain, aux_wakeref); 406 out_unlock: 407 if (is_tc_port) 408 intel_tc_port_unlock(dig_port); 409 410 return ret; 411 } 412
On Mon, 19 Jun 2023, Arun R Murthy <arun.r.murthy@intel.com> wrote: > At the beginning of the aux transfer a check for aux control busy bit is > done. Then as per the spec on aux transfer timeout, need to retry > freshly for 3 times with a delay which is taken care by the control > register. > On each of these 3 trials a check for busy has to be done so as to start > freshly. > > v2: updated the commit message > v4: check for SEND_BUSY after write (Imre) > > Signed-off-by: Arun R Murthy <arun.r.murthy@intel.com> > --- > drivers/gpu/drm/i915/display/intel_dp_aux.c | 58 +++++++++------------ > 1 file changed, 26 insertions(+), 32 deletions(-) > > diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux.c b/drivers/gpu/drm/i915/display/intel_dp_aux.c > index 21b50a5c8a85..abe8047fac39 100644 > --- a/drivers/gpu/drm/i915/display/intel_dp_aux.c > +++ b/drivers/gpu/drm/i915/display/intel_dp_aux.c > @@ -226,6 +226,7 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp, > int i, ret, recv_bytes; > int try, clock = 0; > u32 status; > + u32 send_ctl; > bool vdd; > > ch_ctl = intel_dp->aux_ch_ctl_reg(intel_dp); > @@ -273,45 +274,36 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp, > * it using the same AUX CH simultaneously > */ > > - /* Try to wait for any previous AUX channel activity */ > - for (try = 0; try < 3; try++) { > - status = intel_de_read_notrace(i915, ch_ctl); > - if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0) > - break; > - msleep(1); > - } > - /* just trace the final value */ > - trace_i915_reg_rw(false, ch_ctl, status, sizeof(status), true); > - > - if (try == 3) { > - const u32 status = intel_de_read(i915, ch_ctl); > - > - if (status != intel_dp->aux_busy_last_status) { > - drm_WARN(&i915->drm, 1, > - "%s: not started (status 0x%08x)\n", > - intel_dp->aux.name, status); > - intel_dp->aux_busy_last_status = status; > - } > - > - ret = -EBUSY; > - goto out; > - } > - > /* Only 5 data registers! */ > if (drm_WARN_ON(&i915->drm, send_bytes > 20 || recv_size > 20)) { > ret = -E2BIG; > goto out; > } > + send_ctl = intel_dp->get_aux_send_ctl(intel_dp, > + send_bytes, > + aux_clock_divider); > + send_ctl |= aux_send_ctl_flags; > > while ((aux_clock_divider = intel_dp->get_aux_clock_divider(intel_dp, clock++))) { > - u32 send_ctl = intel_dp->get_aux_send_ctl(intel_dp, > - send_bytes, > - aux_clock_divider); > - > - send_ctl |= aux_send_ctl_flags; You can't move the send_ctl assignment outside the loop, because the loop changes aux_clock_divider which affects send_ctl. Please take your time with the next version, and don't try to rush it, and we'll get this done quicker. > - > - /* Must try at least 3 times according to DP spec */ > + /* Re-visit : Must try at least 3 times according to DP spec */ How is this change helpful? > for (try = 0; try < 5; try++) { > + /* Try to wait for any previous AUX channel activity */ > + status = intel_dp_aux_wait_done(intel_dp); > + /* just trace the final value */ > + trace_i915_reg_rw(false, ch_ctl, status, sizeof(status), true); > + > + if (status & DP_AUX_CH_CTL_SEND_BUSY) { > + drm_WARN(&i915->drm, 1, > + "%s: not started, previous Tx still in process (status 0x%08x)\n", > + intel_dp->aux.name, status); > + intel_dp->aux_busy_last_status = status; > + if (try > 3) { > + ret = -EBUSY; > + goto out; > + } else > + continue; If one branch needs braces, all of them do. > + } > + > /* Load the send data into the aux channel data registers */ > for (i = 0; i < send_bytes; i += 4) > intel_de_write(i915, ch_data[i >> 2], > @@ -321,6 +313,7 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp, > /* Send the command and wait for it to complete */ > intel_de_write(i915, ch_ctl, send_ctl); > > + /* TODO: if typeC then 4.2ms else 800us. For DG2 add 1.5ms for both cases */ > status = intel_dp_aux_wait_done(intel_dp); > > /* Clear done status and any errors */ > @@ -335,7 +328,8 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp, > * Timeout errors from the HW already meet this > * requirement so skip to next iteration > */ > - if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR) > + if (status & (DP_AUX_CH_CTL_TIME_OUT_ERROR | > + DP_AUX_CH_CTL_SEND_BUSY)) The indentation is off. > continue; > > if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) {
> -----Original Message----- > From: Nikula, Jani <jani.nikula@intel.com> > Sent: Monday, June 19, 2023 5:37 PM > To: Murthy, Arun R <arun.r.murthy@intel.com>; intel- > gfx@lists.freedesktop.org > Cc: Deak, Imre <imre.deak@intel.com>; Kahola, Mika > <mika.kahola@intel.com>; Murthy, Arun R <arun.r.murthy@intel.com> > Subject: Re: [PATCHv4] drm/i915/display/dp: On AUX xfer timeout restart > freshly > > On Mon, 19 Jun 2023, Arun R Murthy <arun.r.murthy@intel.com> wrote: > > At the beginning of the aux transfer a check for aux control busy bit > > is done. Then as per the spec on aux transfer timeout, need to retry > > freshly for 3 times with a delay which is taken care by the control > > register. > > On each of these 3 trials a check for busy has to be done so as to > > start freshly. > > > > v2: updated the commit message > > v4: check for SEND_BUSY after write (Imre) > > > > Signed-off-by: Arun R Murthy <arun.r.murthy@intel.com> > > --- > > drivers/gpu/drm/i915/display/intel_dp_aux.c | 58 > > +++++++++------------ > > 1 file changed, 26 insertions(+), 32 deletions(-) > > > > diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux.c > > b/drivers/gpu/drm/i915/display/intel_dp_aux.c > > index 21b50a5c8a85..abe8047fac39 100644 > > --- a/drivers/gpu/drm/i915/display/intel_dp_aux.c > > +++ b/drivers/gpu/drm/i915/display/intel_dp_aux.c > > @@ -226,6 +226,7 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp, > > int i, ret, recv_bytes; > > int try, clock = 0; > > u32 status; > > + u32 send_ctl; > > bool vdd; > > > > ch_ctl = intel_dp->aux_ch_ctl_reg(intel_dp); > > @@ -273,45 +274,36 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp, > > * it using the same AUX CH simultaneously > > */ > > > > - /* Try to wait for any previous AUX channel activity */ > > - for (try = 0; try < 3; try++) { > > - status = intel_de_read_notrace(i915, ch_ctl); > > - if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0) > > - break; > > - msleep(1); > > - } > > - /* just trace the final value */ > > - trace_i915_reg_rw(false, ch_ctl, status, sizeof(status), true); > > - > > - if (try == 3) { > > - const u32 status = intel_de_read(i915, ch_ctl); > > - > > - if (status != intel_dp->aux_busy_last_status) { > > - drm_WARN(&i915->drm, 1, > > - "%s: not started (status 0x%08x)\n", > > - intel_dp->aux.name, status); > > - intel_dp->aux_busy_last_status = status; > > - } > > - > > - ret = -EBUSY; > > - goto out; > > - } > > - > > /* Only 5 data registers! */ > > if (drm_WARN_ON(&i915->drm, send_bytes > 20 || recv_size > 20)) { > > ret = -E2BIG; > > goto out; > > } > > + send_ctl = intel_dp->get_aux_send_ctl(intel_dp, > > + send_bytes, > > + aux_clock_divider); > > + send_ctl |= aux_send_ctl_flags; > > > > while ((aux_clock_divider = intel_dp- > >get_aux_clock_divider(intel_dp, clock++))) { > > - u32 send_ctl = intel_dp->get_aux_send_ctl(intel_dp, > > - send_bytes, > > - aux_clock_divider); > > - > > - send_ctl |= aux_send_ctl_flags; > > You can't move the send_ctl assignment outside the loop, because the loop > changes aux_clock_divider which affects send_ctl. > > Please take your time with the next version, and don't try to rush it, and we'll > get this done quicker. Sure. > > > - > > - /* Must try at least 3 times according to DP spec */ > > + /* Re-visit : Must try at least 3 times according to DP spec */ > > How is this change helpful? There was a comment on the earlier patch for the retry count. Here we are retrying for 5 times but the spec says retry for 3 times. Need to revisit this to see if there is any WA/recommendation in Bspec and to update the same with link or revert it to 3 times. > > > for (try = 0; try < 5; try++) { > > + /* Try to wait for any previous AUX channel activity > */ > > + status = intel_dp_aux_wait_done(intel_dp); > > + /* just trace the final value */ > > + trace_i915_reg_rw(false, ch_ctl, status, sizeof(status), > true); > > + > > + if (status & DP_AUX_CH_CTL_SEND_BUSY) { > > + drm_WARN(&i915->drm, 1, > > + "%s: not started, previous Tx still in > process (status 0x%08x)\n", > > + intel_dp->aux.name, status); > > + intel_dp->aux_busy_last_status = status; > > + if (try > 3) { > > + ret = -EBUSY; > > + goto out; > > + } else > > + continue; > > If one branch needs braces, all of them do. > Ok. Thanks and Regards, Arun R Murthy -------------------- > > + } > > + > > /* Load the send data into the aux channel data > registers */ > > for (i = 0; i < send_bytes; i += 4) > > intel_de_write(i915, ch_data[i >> 2], @@ - > 321,6 +313,7 @@ > > intel_dp_aux_xfer(struct intel_dp *intel_dp, > > /* Send the command and wait for it to complete */ > > intel_de_write(i915, ch_ctl, send_ctl); > > > > + /* TODO: if typeC then 4.2ms else 800us. For DG2 > add 1.5ms for > > +both cases */ > > status = intel_dp_aux_wait_done(intel_dp); > > > > /* Clear done status and any errors */ @@ -335,7 > +328,8 @@ > > intel_dp_aux_xfer(struct intel_dp *intel_dp, > > * Timeout errors from the HW already meet this > > * requirement so skip to next iteration > > */ > > - if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR) > > + if (status & (DP_AUX_CH_CTL_TIME_OUT_ERROR | > > + > DP_AUX_CH_CTL_SEND_BUSY)) > > The indentation is off. > > > continue; > > > > if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) { > > -- > Jani Nikula, Intel Open Source Graphics Center
diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux.c b/drivers/gpu/drm/i915/display/intel_dp_aux.c index 21b50a5c8a85..abe8047fac39 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux.c @@ -226,6 +226,7 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp, int i, ret, recv_bytes; int try, clock = 0; u32 status; + u32 send_ctl; bool vdd; ch_ctl = intel_dp->aux_ch_ctl_reg(intel_dp); @@ -273,45 +274,36 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp, * it using the same AUX CH simultaneously */ - /* Try to wait for any previous AUX channel activity */ - for (try = 0; try < 3; try++) { - status = intel_de_read_notrace(i915, ch_ctl); - if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0) - break; - msleep(1); - } - /* just trace the final value */ - trace_i915_reg_rw(false, ch_ctl, status, sizeof(status), true); - - if (try == 3) { - const u32 status = intel_de_read(i915, ch_ctl); - - if (status != intel_dp->aux_busy_last_status) { - drm_WARN(&i915->drm, 1, - "%s: not started (status 0x%08x)\n", - intel_dp->aux.name, status); - intel_dp->aux_busy_last_status = status; - } - - ret = -EBUSY; - goto out; - } - /* Only 5 data registers! */ if (drm_WARN_ON(&i915->drm, send_bytes > 20 || recv_size > 20)) { ret = -E2BIG; goto out; } + send_ctl = intel_dp->get_aux_send_ctl(intel_dp, + send_bytes, + aux_clock_divider); + send_ctl |= aux_send_ctl_flags; while ((aux_clock_divider = intel_dp->get_aux_clock_divider(intel_dp, clock++))) { - u32 send_ctl = intel_dp->get_aux_send_ctl(intel_dp, - send_bytes, - aux_clock_divider); - - send_ctl |= aux_send_ctl_flags; - - /* Must try at least 3 times according to DP spec */ + /* Re-visit : Must try at least 3 times according to DP spec */ for (try = 0; try < 5; try++) { + /* Try to wait for any previous AUX channel activity */ + status = intel_dp_aux_wait_done(intel_dp); + /* just trace the final value */ + trace_i915_reg_rw(false, ch_ctl, status, sizeof(status), true); + + if (status & DP_AUX_CH_CTL_SEND_BUSY) { + drm_WARN(&i915->drm, 1, + "%s: not started, previous Tx still in process (status 0x%08x)\n", + intel_dp->aux.name, status); + intel_dp->aux_busy_last_status = status; + if (try > 3) { + ret = -EBUSY; + goto out; + } else + continue; + } + /* Load the send data into the aux channel data registers */ for (i = 0; i < send_bytes; i += 4) intel_de_write(i915, ch_data[i >> 2], @@ -321,6 +313,7 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp, /* Send the command and wait for it to complete */ intel_de_write(i915, ch_ctl, send_ctl); + /* TODO: if typeC then 4.2ms else 800us. For DG2 add 1.5ms for both cases */ status = intel_dp_aux_wait_done(intel_dp); /* Clear done status and any errors */ @@ -335,7 +328,8 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp, * Timeout errors from the HW already meet this * requirement so skip to next iteration */ - if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR) + if (status & (DP_AUX_CH_CTL_TIME_OUT_ERROR | + DP_AUX_CH_CTL_SEND_BUSY)) continue; if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) {
At the beginning of the aux transfer a check for aux control busy bit is done. Then as per the spec on aux transfer timeout, need to retry freshly for 3 times with a delay which is taken care by the control register. On each of these 3 trials a check for busy has to be done so as to start freshly. v2: updated the commit message v4: check for SEND_BUSY after write (Imre) Signed-off-by: Arun R Murthy <arun.r.murthy@intel.com> --- drivers/gpu/drm/i915/display/intel_dp_aux.c | 58 +++++++++------------ 1 file changed, 26 insertions(+), 32 deletions(-)