]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
nouveau/dp: handle retries for AUX CH transfers with GSP.
authorDave Airlie <airlied@redhat.com>
Mon, 11 Nov 2024 03:41:25 +0000 (13:41 +1000)
committerDave Airlie <airlied@redhat.com>
Thu, 14 Nov 2024 01:50:01 +0000 (11:50 +1000)
eb284f4b3781 drm/nouveau/dp: Honor GSP link training retry timeouts

tried to fix a problem with panel retires, however it appears
the auxch also needs the same treatment, so add the same retry
wrapper around it.

This fixes some eDP panels after a suspend/resume cycle.

Fixes: eb284f4b3781 ("drm/nouveau/dp: Honor GSP link training retry timeouts")
Cc: stable@vger.kernel.org
Reviewed-by: Lyude Paul <lyude@redhat.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20241111034126.2028401-2-airlied@gmail.com
drivers/gpu/drm/nouveau/nvkm/engine/disp/r535.c

index 8f9aa3463c3c9281c7f2d5e85a2cacece86d5460..99110ab2f44dcd83395425a71329c0fad9fe0862 100644 (file)
@@ -1060,33 +1060,44 @@ r535_dp_aux_xfer(struct nvkm_outp *outp, u8 type, u32 addr, u8 *data, u8 *psize)
        NV0073_CTRL_DP_AUXCH_CTRL_PARAMS *ctrl;
        u8 size = *psize;
        int ret;
+       int retries;
 
-       ctrl = nvkm_gsp_rm_ctrl_get(&disp->rm.objcom, NV0073_CTRL_CMD_DP_AUXCH_CTRL, sizeof(*ctrl));
-       if (IS_ERR(ctrl))
-               return PTR_ERR(ctrl);
+       for (retries = 0; retries < 3; ++retries) {
+               ctrl = nvkm_gsp_rm_ctrl_get(&disp->rm.objcom, NV0073_CTRL_CMD_DP_AUXCH_CTRL, sizeof(*ctrl));
+               if (IS_ERR(ctrl))
+                       return PTR_ERR(ctrl);
 
-       ctrl->subDeviceInstance = 0;
-       ctrl->displayId = BIT(outp->index);
-       ctrl->bAddrOnly = !size;
-       ctrl->cmd = type;
-       if (ctrl->bAddrOnly) {
-               ctrl->cmd = NVDEF_SET(ctrl->cmd, NV0073_CTRL, DP_AUXCH_CMD, REQ_TYPE, WRITE);
-               ctrl->cmd = NVDEF_SET(ctrl->cmd, NV0073_CTRL, DP_AUXCH_CMD,  I2C_MOT, FALSE);
-       }
-       ctrl->addr = addr;
-       ctrl->size = !ctrl->bAddrOnly ? (size - 1) : 0;
-       memcpy(ctrl->data, data, size);
+               ctrl->subDeviceInstance = 0;
+               ctrl->displayId = BIT(outp->index);
+               ctrl->bAddrOnly = !size;
+               ctrl->cmd = type;
+               if (ctrl->bAddrOnly) {
+                       ctrl->cmd = NVDEF_SET(ctrl->cmd, NV0073_CTRL, DP_AUXCH_CMD, REQ_TYPE, WRITE);
+                       ctrl->cmd = NVDEF_SET(ctrl->cmd, NV0073_CTRL, DP_AUXCH_CMD,  I2C_MOT, FALSE);
+               }
+               ctrl->addr = addr;
+               ctrl->size = !ctrl->bAddrOnly ? (size - 1) : 0;
+               memcpy(ctrl->data, data, size);
 
-       ret = nvkm_gsp_rm_ctrl_push(&disp->rm.objcom, &ctrl, sizeof(*ctrl));
-       if (ret) {
-               nvkm_gsp_rm_ctrl_done(&disp->rm.objcom, ctrl);
-               return ret;
+               ret = nvkm_gsp_rm_ctrl_push(&disp->rm.objcom, &ctrl, sizeof(*ctrl));
+               if ((ret == -EAGAIN || ret == -EBUSY) && ctrl->retryTimeMs) {
+                       /*
+                        * Device (likely an eDP panel) isn't ready yet, wait for the time specified
+                        * by GSP before retrying again
+                        */
+                       nvkm_debug(&disp->engine.subdev,
+                                  "Waiting %dms for GSP LT panel delay before retrying in AUX\n",
+                                  ctrl->retryTimeMs);
+                       msleep(ctrl->retryTimeMs);
+                       nvkm_gsp_rm_ctrl_done(&disp->rm.objcom, ctrl);
+               } else {
+                       memcpy(data, ctrl->data, size);
+                       *psize = ctrl->size;
+                       ret = ctrl->replyType;
+                       nvkm_gsp_rm_ctrl_done(&disp->rm.objcom, ctrl);
+                       break;
+               }
        }
-
-       memcpy(data, ctrl->data, size);
-       *psize = ctrl->size;
-       ret = ctrl->replyType;
-       nvkm_gsp_rm_ctrl_done(&disp->rm.objcom, ctrl);
        return ret;
 }