From 1af5c410cc0cae4808fd25e5cd88de303b8975fd Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 1 Mar 2017 09:01:08 +1000 Subject: [PATCH] drm/nouveau/i2c: modify aux interface to return length actually transferred Apparently sinks are allows to respond with ACK even if they didn't fully complete a transaction... It seems like a missed opportunity for DEFER to me, but what do I know :) Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h | 8 +++++--- drivers/gpu/drm/nouveau/nouveau_connector.c | 5 +++-- drivers/gpu/drm/nouveau/nvkm/subdev/i2c/anx9805.c | 14 +++++++------- drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c | 4 ++-- drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.h | 4 ++-- drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxg94.c | 10 +++++----- drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm200.c | 10 +++++----- 7 files changed, 29 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h index a63c5ac69f66..ce23cc6c672e 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h @@ -64,7 +64,7 @@ void nvkm_i2c_aux_monitor(struct nvkm_i2c_aux *, bool monitor); int nvkm_i2c_aux_acquire(struct nvkm_i2c_aux *); void nvkm_i2c_aux_release(struct nvkm_i2c_aux *); int nvkm_i2c_aux_xfer(struct nvkm_i2c_aux *, bool retry, u8 type, - u32 addr, u8 *data, u8 size); + u32 addr, u8 *data, u8 *size); int nvkm_i2c_aux_lnk_ctl(struct nvkm_i2c_aux *, int link_nr, int link_bw, bool enhanced_framing); @@ -162,9 +162,11 @@ nvkm_probe_i2c(struct i2c_adapter *adap, u8 addr) static inline int nvkm_rdaux(struct nvkm_i2c_aux *aux, u32 addr, u8 *data, u8 size) { + const u8 xfer = size; int ret = nvkm_i2c_aux_acquire(aux); if (ret == 0) { - ret = nvkm_i2c_aux_xfer(aux, true, 9, addr, data, size); + ret = nvkm_i2c_aux_xfer(aux, true, 9, addr, data, &size); + WARN_ON(!ret && size != xfer); nvkm_i2c_aux_release(aux); } return ret; @@ -175,7 +177,7 @@ nvkm_wraux(struct nvkm_i2c_aux *aux, u32 addr, u8 *data, u8 size) { int ret = nvkm_i2c_aux_acquire(aux); if (ret == 0) { - ret = nvkm_i2c_aux_xfer(aux, true, 8, addr, data, size); + ret = nvkm_i2c_aux_xfer(aux, true, 8, addr, data, &size); nvkm_i2c_aux_release(aux); } return ret; diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index f5add64c093f..f802bcd94457 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -1147,6 +1147,7 @@ nouveau_connector_aux_xfer(struct drm_dp_aux *obj, struct drm_dp_aux_msg *msg) container_of(obj, typeof(*nv_connector), aux); struct nouveau_encoder *nv_encoder; struct nvkm_i2c_aux *aux; + u8 size = msg->size; int ret; nv_encoder = find_encoder(&nv_connector->base, DCB_OUTPUT_DP); @@ -1162,11 +1163,11 @@ nouveau_connector_aux_xfer(struct drm_dp_aux *obj, struct drm_dp_aux_msg *msg) return ret; ret = nvkm_i2c_aux_xfer(aux, false, msg->request, msg->address, - msg->buffer, msg->size); + msg->buffer, &size); nvkm_i2c_aux_release(aux); if (ret >= 0) { msg->reply = ret; - return msg->size; + return size; } return ret; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/anx9805.c b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/anx9805.c index b7b01c3f7037..dd391809fef7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/anx9805.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/anx9805.c @@ -134,7 +134,7 @@ struct anx9805_aux { static int anx9805_aux_xfer(struct nvkm_i2c_aux *base, bool retry, - u8 type, u32 addr, u8 *data, u8 size) + u8 type, u32 addr, u8 *data, u8 *size) { struct anx9805_aux *aux = anx9805_aux(base); struct anx9805_pad *pad = aux->pad; @@ -143,7 +143,7 @@ anx9805_aux_xfer(struct nvkm_i2c_aux *base, bool retry, u8 buf[16] = {}; u8 tmp; - AUX_DBG(&aux->base, "%02x %05x %d", type, addr, size); + AUX_DBG(&aux->base, "%02x %05x %d", type, addr, *size); tmp = nvkm_rdi2cr(adap, pad->addr, 0x07) & ~0x04; nvkm_wri2cr(adap, pad->addr, 0x07, tmp | 0x04); @@ -152,12 +152,12 @@ anx9805_aux_xfer(struct nvkm_i2c_aux *base, bool retry, nvkm_wri2cr(adap, aux->addr, 0xe4, 0x80); if (!(type & 1)) { - memcpy(buf, data, size); + memcpy(buf, data, *size); AUX_DBG(&aux->base, "%16ph", buf); - for (i = 0; i < size; i++) + for (i = 0; i < *size; i++) nvkm_wri2cr(adap, aux->addr, 0xf0 + i, buf[i]); } - nvkm_wri2cr(adap, aux->addr, 0xe5, ((size - 1) << 4) | type); + nvkm_wri2cr(adap, aux->addr, 0xe5, ((*size - 1) << 4) | type); nvkm_wri2cr(adap, aux->addr, 0xe6, (addr & 0x000ff) >> 0); nvkm_wri2cr(adap, aux->addr, 0xe7, (addr & 0x0ff00) >> 8); nvkm_wri2cr(adap, aux->addr, 0xe8, (addr & 0xf0000) >> 16); @@ -176,10 +176,10 @@ anx9805_aux_xfer(struct nvkm_i2c_aux *base, bool retry, } if (type & 1) { - for (i = 0; i < size; i++) + for (i = 0; i < *size; i++) buf[i] = nvkm_rdi2cr(adap, aux->addr, 0xf0 + i); AUX_DBG(&aux->base, "%16ph", buf); - memcpy(data, buf, size); + memcpy(data, buf, *size); } ret = 0; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c index 01d5c5a56e2e..d172e42dd228 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c @@ -51,7 +51,7 @@ nvkm_i2c_aux_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) if (mcnt || remaining > 16) cmd |= 4; /* MOT */ - ret = aux->func->xfer(aux, true, cmd, msg->addr, ptr, cnt); + ret = aux->func->xfer(aux, true, cmd, msg->addr, ptr, &cnt); if (ret < 0) { nvkm_i2c_aux_release(aux); return ret; @@ -115,7 +115,7 @@ nvkm_i2c_aux_acquire(struct nvkm_i2c_aux *aux) int nvkm_i2c_aux_xfer(struct nvkm_i2c_aux *aux, bool retry, u8 type, - u32 addr, u8 *data, u8 size) + u32 addr, u8 *data, u8 *size) { return aux->func->xfer(aux, retry, type, addr, data, size); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.h b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.h index fc6b162fa0b1..27a4a39c87f0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.h @@ -4,7 +4,7 @@ struct nvkm_i2c_aux_func { int (*xfer)(struct nvkm_i2c_aux *, bool retry, u8 type, - u32 addr, u8 *data, u8 size); + u32 addr, u8 *data, u8 *size); int (*lnk_ctl)(struct nvkm_i2c_aux *, int link_nr, int link_bw, bool enhanced_framing); }; @@ -15,7 +15,7 @@ int nvkm_i2c_aux_new_(const struct nvkm_i2c_aux_func *, struct nvkm_i2c_pad *, int id, struct nvkm_i2c_aux **); void nvkm_i2c_aux_del(struct nvkm_i2c_aux **); int nvkm_i2c_aux_xfer(struct nvkm_i2c_aux *, bool retry, u8 type, - u32 addr, u8 *data, u8 size); + u32 addr, u8 *data, u8 *size); int g94_i2c_aux_new(struct nvkm_i2c_pad *, int, u8, struct nvkm_i2c_aux **); int gm200_i2c_aux_new(struct nvkm_i2c_pad *, int, u8, struct nvkm_i2c_aux **); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxg94.c b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxg94.c index b80236a4eeac..dc96afb7793c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxg94.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxg94.c @@ -74,7 +74,7 @@ g94_i2c_aux_init(struct g94_i2c_aux *aux) static int g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry, - u8 type, u32 addr, u8 *data, u8 size) + u8 type, u32 addr, u8 *data, u8 *size) { struct g94_i2c_aux *aux = g94_i2c_aux(obj); struct nvkm_device *device = aux->base.pad->i2c->subdev.device; @@ -83,7 +83,7 @@ g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry, u32 xbuf[4] = {}; int ret, i; - AUX_TRACE(&aux->base, "%d: %08x %d", type, addr, size); + AUX_TRACE(&aux->base, "%d: %08x %d", type, addr, *size); ret = g94_i2c_aux_init(aux); if (ret < 0) @@ -97,7 +97,7 @@ g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry, } if (!(type & 1)) { - memcpy(xbuf, data, size); + memcpy(xbuf, data, *size); for (i = 0; i < 16; i += 4) { AUX_TRACE(&aux->base, "wr %08x", xbuf[i / 4]); nvkm_wr32(device, 0x00e4c0 + base + i, xbuf[i / 4]); @@ -107,7 +107,7 @@ g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry, ctrl = nvkm_rd32(device, 0x00e4e4 + base); ctrl &= ~0x0001f0ff; ctrl |= type << 12; - ctrl |= size - 1; + ctrl |= *size - 1; nvkm_wr32(device, 0x00e4e0 + base, addr); /* (maybe) retry transaction a number of times on failure... */ @@ -151,7 +151,7 @@ g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry, xbuf[i / 4] = nvkm_rd32(device, 0x00e4d0 + base + i); AUX_TRACE(&aux->base, "rd %08x", xbuf[i / 4]); } - memcpy(data, xbuf, size); + memcpy(data, xbuf, *size); } out: diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm200.c index ed458c7f056b..50e79a9106a0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm200.c @@ -74,7 +74,7 @@ gm200_i2c_aux_init(struct gm200_i2c_aux *aux) static int gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry, - u8 type, u32 addr, u8 *data, u8 size) + u8 type, u32 addr, u8 *data, u8 *size) { struct gm200_i2c_aux *aux = gm200_i2c_aux(obj); struct nvkm_device *device = aux->base.pad->i2c->subdev.device; @@ -83,7 +83,7 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry, u32 xbuf[4] = {}; int ret, i; - AUX_TRACE(&aux->base, "%d: %08x %d", type, addr, size); + AUX_TRACE(&aux->base, "%d: %08x %d", type, addr, *size); ret = gm200_i2c_aux_init(aux); if (ret < 0) @@ -97,7 +97,7 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry, } if (!(type & 1)) { - memcpy(xbuf, data, size); + memcpy(xbuf, data, *size); for (i = 0; i < 16; i += 4) { AUX_TRACE(&aux->base, "wr %08x", xbuf[i / 4]); nvkm_wr32(device, 0x00d930 + base + i, xbuf[i / 4]); @@ -107,7 +107,7 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry, ctrl = nvkm_rd32(device, 0x00d954 + base); ctrl &= ~0x0001f0ff; ctrl |= type << 12; - ctrl |= size - 1; + ctrl |= *size - 1; nvkm_wr32(device, 0x00d950 + base, addr); /* (maybe) retry transaction a number of times on failure... */ @@ -151,7 +151,7 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry, xbuf[i / 4] = nvkm_rd32(device, 0x00d940 + base + i); AUX_TRACE(&aux->base, "rd %08x", xbuf[i / 4]); } - memcpy(data, xbuf, size); + memcpy(data, xbuf, *size); } out: