summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm200.c
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2016-11-03 07:37:33 +0100
committerBen Skeggs <bskeggs@redhat.com>2016-11-07 05:04:30 +0100
commitf1963a47c0a986b6d13e11136a2a6f873786c5f2 (patch)
tree012184b8f96db878058ba6b0983de137f1331c6b /drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm200.c
parentdrm/nouveau/kms: lvds panel strap moved again on maxwell (diff)
downloadlinux-f1963a47c0a986b6d13e11136a2a6f873786c5f2.tar.xz
linux-f1963a47c0a986b6d13e11136a2a6f873786c5f2.zip
drm/nouveau/i2c/aux/g94-: retry transactions after hw reports an error
This fixes (works around?) link training failures seen on (at least) the Lenovo P50's internal panel. It's also an important fix on the same system for MST support on the dock. Sometimes, right after receiving an IRQ from the sink, there's an error bit (SINKSTAT_ERR) set in the DPAUX registers before we've even attempted a transaction. v2. Fixed regression on passive DP->DVI adapters. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm200.c')
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm200.c10
1 files changed, 5 insertions, 5 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm200.c
index 61d729b82c69..ed458c7f056b 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm200.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm200.c
@@ -79,7 +79,7 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
struct gm200_i2c_aux *aux = gm200_i2c_aux(obj);
struct nvkm_device *device = aux->base.pad->i2c->subdev.device;
const u32 base = aux->ch * 0x50;
- u32 ctrl, stat, timeout, retries;
+ u32 ctrl, stat, timeout, retries = 0;
u32 xbuf[4] = {};
int ret, i;
@@ -111,7 +111,7 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
nvkm_wr32(device, 0x00d950 + base, addr);
/* (maybe) retry transaction a number of times on failure... */
- for (retries = 0; !ret && retries < 32; retries++) {
+ do {
/* reset, and delay a while if this is a retry */
nvkm_wr32(device, 0x00d954 + base, 0x80000000 | ctrl);
nvkm_wr32(device, 0x00d954 + base, 0x00000000 | ctrl);
@@ -131,20 +131,20 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
goto out;
}
} while (ctrl & 0x00010000);
- ret = 1;
+ ret = 0;
/* read status, and check if transaction completed ok */
stat = nvkm_mask(device, 0x00d958 + base, 0, 0);
if ((stat & 0x000f0000) == 0x00080000 ||
(stat & 0x000f0000) == 0x00020000)
- ret = retry ? 0 : 1;
+ ret = 1;
if ((stat & 0x00000100))
ret = -ETIMEDOUT;
if ((stat & 0x00000e00))
ret = -EIO;
AUX_TRACE(&aux->base, "%02d %08x %08x", retries, ctrl, stat);
- }
+ } while (ret && retry && retries++ < 32);
if (type & 1) {
for (i = 0; i < 16; i += 4) {