]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
accel/ivpu: Abort jobs of faulty context
authorMaciej Falkowski <maciej.falkowski@intel.com>
Tue, 11 Jun 2024 12:04:19 +0000 (14:04 +0200)
committerJacek Lawrynowicz <jacek.lawrynowicz@linux.intel.com>
Fri, 14 Jun 2024 07:12:11 +0000 (09:12 +0200)
Abort all jobs that belong to contexts generating MMU faults in order
to avoid flooding host with MMU IRQs.

Jobs are cancelled with:
  - SSID_RELEASE command when OS scheduling is enabled
  - DESTROY_CMDQ command when HW scheduling is enabled

Signed-off-by: Maciej Falkowski <maciej.falkowski@intel.com>
Co-developed-by: Wachowski, Karol <karol.wachowski@intel.com>
Signed-off-by: Wachowski, Karol <karol.wachowski@intel.com>
Reviewed-by: Jacek Lawrynowicz <jacek.lawrynowicz@linux.intel.com>
Signed-off-by: Jacek Lawrynowicz <jacek.lawrynowicz@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240611120433.1012423-3-jacek.lawrynowicz@linux.intel.com
drivers/accel/ivpu/ivpu_drv.c
drivers/accel/ivpu/ivpu_drv.h
drivers/accel/ivpu/ivpu_hw.h
drivers/accel/ivpu/ivpu_ipc.c
drivers/accel/ivpu/ivpu_ipc.h
drivers/accel/ivpu/ivpu_job.c
drivers/accel/ivpu/ivpu_job.h
drivers/accel/ivpu/ivpu_jsm_msg.c
drivers/accel/ivpu/ivpu_mmu.c

index f3e0d55f4adb83f736d3ad157ec3fb5145822052..3ce12b66f699293bfb1fefe730bf9502bb36eb19 100644 (file)
@@ -446,6 +446,26 @@ static const struct drm_driver driver = {
        .minor = DRM_IVPU_DRIVER_MINOR,
 };
 
+static void ivpu_context_abort_invalid(struct ivpu_device *vdev)
+{
+       struct ivpu_file_priv *file_priv;
+       unsigned long ctx_id;
+
+       mutex_lock(&vdev->context_list_lock);
+
+       xa_for_each(&vdev->context_xa, ctx_id, file_priv) {
+               if (!file_priv->has_mmu_faults || file_priv->aborted)
+                       continue;
+
+               mutex_lock(&file_priv->lock);
+               ivpu_context_abort_locked(file_priv);
+               file_priv->aborted = true;
+               mutex_unlock(&file_priv->lock);
+       }
+
+       mutex_unlock(&vdev->context_list_lock);
+}
+
 static irqreturn_t ivpu_irq_thread_handler(int irq, void *arg)
 {
        struct ivpu_device *vdev = arg;
@@ -459,6 +479,9 @@ static irqreturn_t ivpu_irq_thread_handler(int irq, void *arg)
                case IVPU_HW_IRQ_SRC_IPC:
                        ivpu_ipc_irq_thread_handler(vdev);
                        break;
+               case IVPU_HW_IRQ_SRC_MMU_EVTQ:
+                       ivpu_context_abort_invalid(vdev);
+                       break;
                default:
                        ivpu_err_ratelimited(vdev, "Unknown IRQ source: %u\n", irq_src);
                        break;
index 823e10c41816f58625704f85eb301fe4988c2109..dc6ad1978a3bc5b24153d41e28c40999ed624286 100644 (file)
@@ -169,6 +169,7 @@ struct ivpu_file_priv {
        struct ivpu_bo *ms_info_bo;
        bool has_mmu_faults;
        bool bound;
+       bool aborted;
 };
 
 extern int ivpu_dbg_mask;
index 8ddf9f93189d48dfd3d3d2153a62c42ed48dc4dd..1a55538aafdcdd22828e580b454b78c61b3814b4 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Copyright (C) 2020 - 2024 Intel Corporation
+ * Copyright (C) 2020-2024 Intel Corporation
  */
 
 #ifndef __IVPU_HW_H__
@@ -15,6 +15,7 @@
 #define IVPU_HW_IRQ_FIFO_LENGTH 1024
 
 #define IVPU_HW_IRQ_SRC_IPC 1
+#define IVPU_HW_IRQ_SRC_MMU_EVTQ 2
 
 struct ivpu_addr_range {
        resource_size_t start;
index 74ab964d229bb3f4bf73a4952c15e1a6cd2fe58c..78b32a8232419eccf8fa50a931d1874f93d0dff2 100644 (file)
@@ -210,8 +210,7 @@ void ivpu_ipc_consumer_del(struct ivpu_device *vdev, struct ivpu_ipc_consumer *c
        ivpu_ipc_tx_release(vdev, cons->tx_vpu_addr);
 }
 
-static int
-ivpu_ipc_send(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons, struct vpu_jsm_msg *req)
+int ivpu_ipc_send(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons, struct vpu_jsm_msg *req)
 {
        struct ivpu_ipc_info *ipc = vdev->ipc;
        int ret;
index 75f532428d68b2b03a17eaaf33f14272d5cf362b..4fe38141045ea370c40e86b22e682401abb18c2c 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Copyright (C) 2020-2023 Intel Corporation
+ * Copyright (C) 2020-2024 Intel Corporation
  */
 
 #ifndef __IVPU_IPC_H__
@@ -96,6 +96,8 @@ void ivpu_ipc_consumer_add(struct ivpu_device *vdev, struct ivpu_ipc_consumer *c
                           u32 channel, ivpu_ipc_rx_callback_t callback);
 void ivpu_ipc_consumer_del(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons);
 
+int ivpu_ipc_send(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons,
+                 struct vpu_jsm_msg *req);
 int ivpu_ipc_receive(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons,
                     struct ivpu_ipc_hdr *ipc_buf, struct vpu_jsm_msg *jsm_msg,
                     unsigned long timeout_ms);
index e4e24813fe03a6dff148b01e637cfe72b2385897..be2e2bf0f43f022768d02c171130db028237d773 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (C) 2020-2023 Intel Corporation
+ * Copyright (C) 2020-2024 Intel Corporation
  */
 
 #include <drm/drm_file.h>
@@ -312,6 +312,33 @@ void ivpu_cmdq_reset_all_contexts(struct ivpu_device *vdev)
        mutex_unlock(&vdev->context_list_lock);
 }
 
+static void ivpu_cmdq_fini_all(struct ivpu_file_priv *file_priv)
+{
+       u16 engine;
+       u8 priority;
+
+       for (engine = 0; engine < IVPU_NUM_ENGINES; engine++) {
+               for (priority = 0; priority < IVPU_NUM_PRIORITIES; priority++) {
+                       int cmdq_idx = IVPU_CMDQ_INDEX(engine, priority);
+
+                       if (file_priv->cmdq[cmdq_idx])
+                               ivpu_cmdq_fini(file_priv, file_priv->cmdq[cmdq_idx]);
+               }
+       }
+}
+
+void ivpu_context_abort_locked(struct ivpu_file_priv *file_priv)
+{
+       struct ivpu_device *vdev = file_priv->vdev;
+
+       lockdep_assert_held(&file_priv->lock);
+
+       ivpu_cmdq_fini_all(file_priv);
+
+       if (vdev->hw->sched_mode == VPU_SCHEDULING_MODE_OS)
+               ivpu_jsm_context_release(vdev, file_priv->ctx.id);
+}
+
 static int ivpu_cmdq_push_job(struct ivpu_cmdq *cmdq, struct ivpu_job *job)
 {
        struct ivpu_device *vdev = job->vdev;
index e50002b5788c40910d01d6d4729d4bb1e1a1402d..6accb94028c7a2d8468a5418648266c0c6be4890 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Copyright (C) 2020-2023 Intel Corporation
+ * Copyright (C) 2020-2024 Intel Corporation
  */
 
 #ifndef __IVPU_JOB_H__
@@ -57,6 +57,8 @@ struct ivpu_job {
 
 int ivpu_submit_ioctl(struct drm_device *dev, void *data, struct drm_file *file);
 
+void ivpu_context_abort_locked(struct ivpu_file_priv *file_priv);
+
 void ivpu_cmdq_release_all_locked(struct ivpu_file_priv *file_priv);
 void ivpu_cmdq_reset_all_contexts(struct ivpu_device *vdev);
 
index e8dd73d947e42b88f31af72efbad7ab38257a865..3179e80de1ec220bccde5e729cb86d5f0393332c 100644 (file)
@@ -255,11 +255,16 @@ int ivpu_jsm_context_release(struct ivpu_device *vdev, u32 host_ssid)
 {
        struct vpu_jsm_msg req = { .type = VPU_JSM_MSG_SSID_RELEASE };
        struct vpu_jsm_msg resp;
+       int ret;
 
        req.payload.ssid_release.host_ssid = host_ssid;
 
-       return ivpu_ipc_send_receive(vdev, &req, VPU_JSM_MSG_SSID_RELEASE_DONE, &resp,
-                                    VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm);
+       ret = ivpu_ipc_send_receive(vdev, &req, VPU_JSM_MSG_SSID_RELEASE_DONE, &resp,
+                                   VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm);
+       if (ret)
+               ivpu_warn_ratelimited(vdev, "Failed to release context: %d\n", ret);
+
+       return ret;
 }
 
 int ivpu_jsm_pwr_d0i3_enter(struct ivpu_device *vdev)
index 8682e61455208c13bc4c64f6fa61beaa407681ed..c078e214b221297ed606ceccaf641e268f598838 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (C) 2020-2023 Intel Corporation
+ * Copyright (C) 2020-2024 Intel Corporation
  */
 
 #include <linux/circ_buf.h>
@@ -878,8 +878,9 @@ static void ivpu_mmu_dump_event(struct ivpu_device *vdev, u32 *event)
        u64 in_addr = ((u64)event[5]) << 32 | event[4];
        u32 sid = event[1];
 
-       ivpu_err(vdev, "MMU EVTQ: 0x%x (%s) SSID: %d SID: %d, e[2] %08x, e[3] %08x, in addr: 0x%llx, fetch addr: 0x%llx\n",
-                op, ivpu_mmu_event_to_str(op), ssid, sid, event[2], event[3], in_addr, fetch_addr);
+       ivpu_err_ratelimited(vdev, "MMU EVTQ: 0x%x (%s) SSID: %d SID: %d, e[2] %08x, e[3] %08x, in addr: 0x%llx, fetch addr: 0x%llx\n",
+                            op, ivpu_mmu_event_to_str(op), ssid, sid,
+                            event[2], event[3], in_addr, fetch_addr);
 }
 
 static u32 *ivpu_mmu_get_event(struct ivpu_device *vdev)
@@ -915,6 +916,9 @@ void ivpu_mmu_irq_evtq_handler(struct ivpu_device *vdev)
                ivpu_mmu_user_context_mark_invalid(vdev, ssid);
                REGV_WR32(IVPU_MMU_REG_EVTQ_CONS_SEC, vdev->mmu->evtq.cons);
        }
+
+       if (!kfifo_put(&vdev->hw->irq.fifo, IVPU_HW_IRQ_SRC_MMU_EVTQ))
+               ivpu_err_ratelimited(vdev, "IRQ FIFO full\n");
 }
 
 void ivpu_mmu_evtq_dump(struct ivpu_device *vdev)