]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
accel/ivpu: Add FW state dump on TDR
authorTomasz Rusinowicz <tomasz.rusinowicz@intel.com>
Mon, 30 Sep 2024 19:52:59 +0000 (21:52 +0200)
committerJacek Lawrynowicz <jacek.lawrynowicz@linux.intel.com>
Fri, 11 Oct 2024 10:44:38 +0000 (12:44 +0200)
Send JSM state dump message at the beginning of TDR handler. This allows
FW to collect debug info in the FW log before the state of the NPU is
lost allowing to analyze the cause of a TDR.

Wait a predefined timeout (10 ms) so the FW has a chance to write debug
logs. We cannot wait for JSM response at this point because IRQs are
already disabled before TDR handler is invoked.

Signed-off-by: Tomasz Rusinowicz <tomasz.rusinowicz@intel.com>
Reviewed-by: Jacek Lawrynowicz <jacek.lawrynowicz@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240930195322.461209-9-jacek.lawrynowicz@linux.intel.com
Signed-off-by: Jacek Lawrynowicz <jacek.lawrynowicz@linux.intel.com>
drivers/accel/ivpu/ivpu_drv.h
drivers/accel/ivpu/ivpu_hw.c
drivers/accel/ivpu/ivpu_ipc.c
drivers/accel/ivpu/ivpu_ipc.h
drivers/accel/ivpu/ivpu_jsm_msg.c
drivers/accel/ivpu/ivpu_jsm_msg.h
drivers/accel/ivpu/ivpu_pm.c

index 63f13b697eed719367c57f699041fd7d2b9c8337..2b30cc2e9272e40f9a17e47ae7c1f8996f21efb1 100644 (file)
@@ -152,6 +152,7 @@ struct ivpu_device {
                int tdr;
                int autosuspend;
                int d0i3_entry_msg;
+               int state_dump_msg;
        } timeout;
 };
 
index 27f0fe4d54e00628b524d263f817c90075844602..85219e95962150a6578029ab19f728ccfd2b462b 100644 (file)
@@ -89,12 +89,14 @@ static void timeouts_init(struct ivpu_device *vdev)
                vdev->timeout.tdr = 2000000;
                vdev->timeout.autosuspend = -1;
                vdev->timeout.d0i3_entry_msg = 500;
+               vdev->timeout.state_dump_msg = 10;
        } else if (ivpu_is_simics(vdev)) {
                vdev->timeout.boot = 50;
                vdev->timeout.jsm = 500;
                vdev->timeout.tdr = 10000;
                vdev->timeout.autosuspend = -1;
                vdev->timeout.d0i3_entry_msg = 100;
+               vdev->timeout.state_dump_msg = 10;
        } else {
                vdev->timeout.boot = 1000;
                vdev->timeout.jsm = 500;
@@ -104,6 +106,7 @@ static void timeouts_init(struct ivpu_device *vdev)
                else
                        vdev->timeout.autosuspend = 100;
                vdev->timeout.d0i3_entry_msg = 5;
+               vdev->timeout.state_dump_msg = 10;
        }
 }
 
index 78b32a8232419eccf8fa50a931d1874f93d0dff2..83b4ba4f3e20a7772f956dd85434986c897bd456 100644 (file)
@@ -364,6 +364,32 @@ int ivpu_ipc_send_receive(struct ivpu_device *vdev, struct vpu_jsm_msg *req,
        return ret;
 }
 
+int ivpu_ipc_send_and_wait(struct ivpu_device *vdev, struct vpu_jsm_msg *req,
+                          u32 channel, unsigned long timeout_ms)
+{
+       struct ivpu_ipc_consumer cons;
+       int ret;
+
+       ret = ivpu_rpm_get(vdev);
+       if (ret < 0)
+               return ret;
+
+       ivpu_ipc_consumer_add(vdev, &cons, channel, NULL);
+
+       ret = ivpu_ipc_send(vdev, &cons, req);
+       if (ret) {
+               ivpu_warn_ratelimited(vdev, "IPC send failed: %d\n", ret);
+               goto consumer_del;
+       }
+
+       msleep(timeout_ms);
+
+consumer_del:
+       ivpu_ipc_consumer_del(vdev, &cons);
+       ivpu_rpm_put(vdev);
+       return ret;
+}
+
 static bool
 ivpu_ipc_match_consumer(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons,
                        struct ivpu_ipc_hdr *ipc_hdr, struct vpu_jsm_msg *jsm_msg)
index 4fe38141045ea370c40e86b22e682401abb18c2c..6bbe6e32c87490e28f63f6ac204f20f5f52447e8 100644 (file)
@@ -108,5 +108,7 @@ int ivpu_ipc_send_receive_active(struct ivpu_device *vdev, struct vpu_jsm_msg *r
 int ivpu_ipc_send_receive(struct ivpu_device *vdev, struct vpu_jsm_msg *req,
                          enum vpu_ipc_msg_type expected_resp, struct vpu_jsm_msg *resp,
                          u32 channel, unsigned long timeout_ms);
+int ivpu_ipc_send_and_wait(struct ivpu_device *vdev, struct vpu_jsm_msg *req,
+                          u32 channel, unsigned long timeout_ms);
 
 #endif /* __IVPU_IPC_H__ */
index b06da8f50fd3931b22808dd64dd38a82b6a9c242..cd33964d292bc985e7989c84f75172262ca10a4f 100644 (file)
@@ -559,3 +559,11 @@ int ivpu_jsm_dct_disable(struct ivpu_device *vdev)
                                            &resp, VPU_IPC_CHAN_ASYNC_CMD,
                                            vdev->timeout.jsm);
 }
+
+int ivpu_jsm_state_dump(struct ivpu_device *vdev)
+{
+       struct vpu_jsm_msg req = { .type = VPU_JSM_MSG_STATE_DUMP };
+
+       return ivpu_ipc_send_and_wait(vdev, &req, VPU_IPC_CHAN_ASYNC_CMD,
+                                     vdev->timeout.state_dump_msg);
+}
index e4e42c0ff6e65614b36eb7ff52395d6628d9b0e1..9e84d3526a14635cde1d9b3dfe5ef471df67ec90 100644 (file)
@@ -43,4 +43,6 @@ int ivpu_jsm_metric_streamer_info(struct ivpu_device *vdev, u64 metric_group_mas
                                  u64 buffer_size, u32 *sample_size, u64 *info_size);
 int ivpu_jsm_dct_enable(struct ivpu_device *vdev, u32 active_us, u32 inactive_us);
 int ivpu_jsm_dct_disable(struct ivpu_device *vdev);
+int ivpu_jsm_state_dump(struct ivpu_device *vdev);
+
 #endif
index bf77395ffcb7c69832d420a52a3b7563b42b8615..b5a69941e6e0ac5f1534331cf5ba0bc74f5e9229 100644 (file)
@@ -125,6 +125,7 @@ static void ivpu_pm_recovery_work(struct work_struct *work)
        if (ret)
                ivpu_err(vdev, "Failed to resume NPU: %d\n", ret);
 
+       ivpu_jsm_state_dump(vdev);
        ivpu_dev_coredump(vdev);
 
        atomic_inc(&vdev->pm->reset_counter);