[PATCH i-g-t] lib/igt_kms: add retry loop in igt_enable_connectors()

Luca Coelho luca at coelho.fi
Mon May 20 09:01:46 UTC 2024


On Wed, 2024-05-15 at 19:22 +0200, Kamil Konieczny wrote:
> Hi Luca,
> On 2024-05-14 at 12:49:57 +0300, Luca Coelho wrote:
> > Sometimes the connector is not fully initialized yet when we try to
> > read it in igt_enable_connectors() and this causes a warning to be
> > issued and the test to fail.  This can happen in normal situations,
> > because there's no synchronization between the driver and IGT.  In
> > some tests we load the module and immediately start reading the
> > information, but the driver may not be fully initialized at that
> > point, causing the problem.
> > 
> > To prevent this, add a retry loop in igt_enable_connectors() so we
> > retry a few times, after a small delay, to wait for the initialization
> > to complete.
> > 
> > The number of retries and the delay between retries were chose after
> > running lots of tests, but these values may have to be adjusted after
> > running more tests on different machines.
> > 
> > Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/10436
> > Signed-off-by: Luca Coelho <luciano.coelho at intel.com>
> > ---
> >  lib/igt_kms.c | 29 +++++++++++++++++++++++++----
> >  1 file changed, 25 insertions(+), 4 deletions(-)
> > 
> > diff --git a/lib/igt_kms.c b/lib/igt_kms.c
> > index f82102144ea1..3832bf54a2fc 100644
> > --- a/lib/igt_kms.c
> > +++ b/lib/igt_kms.c
> > @@ -5386,7 +5386,10 @@ void igt_wait_for_vblank(int drm_fd, int crtc_offset)
> >   */
> >  void igt_enable_connectors(int drm_fd)
> >  {
> > +#define MAX_TRIES	10
> > +#define SLEEP_DURATION	50000
> >  	drmModeRes *res;
> > +	int tries;
> >  
> >  	res = drmModeGetResources(drm_fd);
> >  	if (!res)
> > @@ -5395,10 +5398,28 @@ void igt_enable_connectors(int drm_fd)
> >  	for (int i = 0; i < res->count_connectors; i++) {
> >  		drmModeConnector *c;
> >  
> > -		/* Do a probe. This may be the first action after booting */
> > -		c = drmModeGetConnector(drm_fd, res->connectors[i]);
> > -		if (!c) {
> > -			igt_warn("Could not read connector %u: %m\n", res->connectors[i]);
> > +		/*
> > +		 * The kernel returns the count of connectors before
> > +		 * they're all fully set up, so we can have a race
> > +		 * condition where we try to get the connector when
> > +		 * it's not fully set up yet.  To avoid failing here
> > +		 * in these cases, retry a few times.
> > +		 */
> > +		for (tries = 0; tries < MAX_TRIES; tries++) {
> > +			/* Do a probe. This may be the first action after booting */
> > +			c = drmModeGetConnector(drm_fd, res->connectors[i]);
> > +			if (c)
> > +				break;
> > +
> > +			igt_info("Could not read connector %u: %m (try %d of %d)\n",
> ----------- ^
> Use igt_debug or print summary after for(tries < MAX_TRIES) loop.

Right, this is better as igt_debug.  I'll change it.


> 
> > +				  res->connectors[i], tries, MAX_TRIES);
> > +
> > +			usleep(SLEEP_DURATION);
> > +		}
> > +
> > +		if (tries == MAX_TRIES) {
> > +			igt_warn("Could not read connector %u after %d tries, skipping\n",
> > +				 res->connectors[i], MAX_TRIES);
> >  			continue;
> 
> How long could it take in worst case?

The values I used were based on a lot of trials on a local machine
where I could reproduce the issue.  We usually pass after the first
retry, which is after a 50 msec delay.  The maximum number of retries I
have needed was 4, which is a 200 msec delay.  This is the worst case I
have seen.  But to be sure, I chose to do 10 retries (500 msecs).

IOW, if everything goes well (i.e. no retry is needed), there's no
additional delay compared to before my patch.  If a retry is needed,
the added delay is going to be between 50 and 200 msecs.

I'll send v2 in a bit.

--
Cheers,
Luca.


More information about the igt-dev mailing list