From: "David R. Hedges" <[email protected]>

Commit eb284f4b3781 ("drm/nouveau/dp: Honor GSP link training retry
timeouts") put the NV0073_CTRL_CMD_DP_CTRL call in
r535_dp_train_target() in a retry loop and dropped the check for the
call failing.  The reply's err field is now read whatever
nvkm_gsp_rm_ctrl_push() returned, but when the GSP RPC itself fails,
a timeout for instance, the reply is NULL.

On a GA102 with GSP-RM 570.144 this turned a display hang into an
oops.  A modeset hit "core notifier timeout", and releasing the output
afterwards timed out waiting for GSP:

  WARNING: nvkm/subdev/gsp/rm/r535/rpc.c:164 at r535_gsp_msgq_wait+0xb1/0xc0 
[nouveau]
  ...
  BUG: kernel NULL pointer dereference, address: 0000000000000010
  RIP: 0010:r535_dp_train_target+0x1db/0x220 [nouveau]
  Call Trace:
   r535_dp_release+0x73/0xe0 [nouveau]
   nvkm_uoutp_mthd+0xaf0/0xc70 [nouveau]
   ...
   nvif_outp_release+0x1b/0xb0 [nouveau]
   nv50_disp_atomic_commit_core+0x5ba/0x6b0 [nouveau]

0x10 is the offset of err in NV0073_CTRL_DP_CTRL_PARAMS.  Only look at
err if the control call succeeded.

Fixes: eb284f4b3781 ("drm/nouveau/dp: Honor GSP link training retry timeouts")
Cc: [email protected]
Link: https://gitlab.freedesktop.org/drm/nouveau/-/work_items/515
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: David R. Hedges <[email protected]>
---
 drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c 
b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c
index 953392504413..028f342e020b 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/disp.c
@@ -1006,7 +1006,7 @@ r535_dp_train_target(struct nvkm_outp *outp, u8 target, 
bool mst, u8 link_nr, u8
                        nvkm_gsp_rm_ctrl_done(&disp->rm.objcom, ctrl);
                } else {
                        /* GSP didn't say to retry, or we were successful */
-                       if (ctrl->err)
+                       if (ret == 0 && ctrl->err)
                                ret = -EIO;
                        nvkm_gsp_rm_ctrl_done(&disp->rm.objcom, ctrl);
                        break;

-- 
2.55.0


Reply via email to