drm/nouveau/i2c: modify aux interface to return length actually transferred
authorBen Skeggs <bskeggs@redhat.com>
Tue, 28 Feb 2017 23:01:08 +0000 (09:01 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Tue, 7 Mar 2017 07:05:16 +0000 (17:05 +1000)
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>
drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h
drivers/gpu/drm/nouveau/nouveau_connector.c
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/anx9805.c
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.h
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxg94.c
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm200.c

index a63c5ac..ce23cc6 100644 (file)
@@ -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;
index f5add64..f802bcd 100644 (file)
@@ -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;
index b7b01c3..dd39180 100644 (file)
@@ -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;
index 01d5c5a..d172e42 100644 (file)
@@ -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);
 }
index fc6b162..27a4a39 100644 (file)
@@ -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 **);
index b80236a..dc96afb 100644 (file)
@@ -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:
index ed458c7..50e79a9 100644 (file)
@@ -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: