On Tue, Mar 15, 2011 at 7:04 AM, Chris Wilson <chris@xxxxxxxxxxxxxxxxxx> wrote: > Usually EDID retrieval is fine. However, sometimes, especially when the > machine is loaded, it fails, but succeeds after a few retries. > > Based on a patch by Michael Buesch. > > Reported-by: Michael Buesch <mb@xxxxxxxxx> > Signed-off-by: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx> Looks good. Reviewed-by: Alex Deucher <alexdeucher@xxxxxxxxx> > --- > > I was going to suggest tuning the i2c_adapter.retries of the affected > components, but that only covers EGAIN and not EREMOTEIO/ETIMEDOUT that > afflicts us. With the alteration to only retry the transfer of the > affected block, this looks to be a reasonable idea and complements the > logic to retry corrupted transfers. > -Chris > > --- > drivers/gpu/drm/drm_edid.c | 44 ++++++++++++++++++++++++++------------------ > 1 files changed, 26 insertions(+), 18 deletions(-) > > diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c > index a245d17..ddc3da9 100644 > --- a/drivers/gpu/drm/drm_edid.c > +++ b/drivers/gpu/drm/drm_edid.c > @@ -230,24 +230,32 @@ drm_do_probe_ddc_edid(struct i2c_adapter *adapter, unsigned char *buf, > int block, int len) > { > unsigned char start = block * EDID_LENGTH; > - struct i2c_msg msgs[] = { > - { > - .addr = DDC_ADDR, > - .flags = 0, > - .len = 1, > - .buf = &start, > - }, { > - .addr = DDC_ADDR, > - .flags = I2C_M_RD, > - .len = len, > - .buf = buf, > - } > - }; > + int ret, retries = 5; > > - if (i2c_transfer(adapter, msgs, 2) == 2) > - return 0; > + /* The core i2c driver will automatically retry the transfer if the > + * adapter reports EAGAIN. However, we find that bit-banging transfers > + * are susceptible to errors under a heavily loaded machine and > + * generate spurious NAKs and timeouts. Retrying the transfer > + * of the individual block a few times seems to overcome this. > + */ > + do { > + struct i2c_msg msgs[] = { > + { > + .addr = DDC_ADDR, > + .flags = 0, > + .len = 1, > + .buf = &start, > + }, { > + .addr = DDC_ADDR, > + .flags = I2C_M_RD, > + .len = len, > + .buf = buf, > + } > + }; > + ret = i2c_transfer(adapter, msgs, 2); > + } while (ret != 2 && --retries); > > - return -1; > + return ret == 2 ? 0 : -1; > } > > static u8 * > -- > 1.7.2.3 > > _______________________________________________ > dri-devel mailing list > dri-devel@xxxxxxxxxxxxxxxxxxxxx > http://lists.freedesktop.org/mailman/listinfo/dri-devel > _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel