summary refs log tree commit diff
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2017-03-01 09:01:08 +1000
committerBen Skeggs <bskeggs@redhat.com>2017-03-07 17:05:16 +1000
commit1af5c410cc0cae4808fd25e5cd88de303b8975fd (patch)
treec4f4a55aca69e4d0bf8e5bec9d1efd5e41e01575
parent36510adde3d9c073a538e441c38515b7741d1732 (diff)
downloadlinux-1af5c410cc0cae4808fd25e5cd88de303b8975fd.tar.gz
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 <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h8
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.c5
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/i2c/anx9805.c14
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.h4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxg94.c10
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm200.c10
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: