accel/ivpu: Abort pending rx ipc on reset
authorStanislaw Gruszka <stanislaw.gruszka@linux.intel.com>
Sat, 28 Oct 2023 15:59:32 +0000 (17:59 +0200)
committerStanislaw Gruszka <stanislaw.gruszka@linux.intel.com>
Tue, 31 Oct 2023 15:25:03 +0000 (16:25 +0100)
Waking up process, which wait for particular condition, will go to
sleep again on wake_up() if the condition is not met. Add abort flag
to wake up IPC receivers, which will finish with -ECANCELED error.

This is only needed for reset, run time power management prevent to
suspend VPU when there is pending IPC processing or pending job.

Reviewed-by: Karol Wachowski <karol.wachowski@linux.intel.com>
Reviewed-by: Jeffrey Hugo <quic_jhugo@quicinc.com>
Signed-off-by: Stanislaw Gruszka <stanislaw.gruszka@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20231028155936.1183342-5-stanislaw.gruszka@linux.intel.com
drivers/accel/ivpu/ivpu_ipc.c
drivers/accel/ivpu/ivpu_ipc.h
drivers/accel/ivpu/ivpu_job.c

index 270caef789bf80fe887b33e4e5a9ba6f0bd508e4..255f2b8b0b5e35de080dbb4d5fc5d611e9fc0e1c 100644 (file)
@@ -148,6 +148,7 @@ ivpu_ipc_consumer_add(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons,
        cons->channel = channel;
        cons->tx_vpu_addr = 0;
        cons->request_id = 0;
+       cons->aborted = false;
        spin_lock_init(&cons->rx_msg_lock);
        INIT_LIST_HEAD(&cons->rx_msg_list);
        init_waitqueue_head(&cons->rx_msg_wq);
@@ -169,7 +170,8 @@ void ivpu_ipc_consumer_del(struct ivpu_device *vdev, struct ivpu_ipc_consumer *c
        spin_lock_irq(&cons->rx_msg_lock);
        list_for_each_entry_safe(rx_msg, r, &cons->rx_msg_list, link) {
                list_del(&rx_msg->link);
-               ivpu_ipc_rx_mark_free(vdev, rx_msg->ipc_hdr, rx_msg->jsm_msg);
+               if (!cons->aborted)
+                       ivpu_ipc_rx_mark_free(vdev, rx_msg->ipc_hdr, rx_msg->jsm_msg);
                atomic_dec(&ipc->rx_msg_count);
                kfree(rx_msg);
        }
@@ -210,7 +212,7 @@ static int ivpu_ipc_rx_need_wakeup(struct ivpu_ipc_consumer *cons)
                ret |= (kthread_should_stop() || kthread_should_park());
 
        spin_lock_irq(&cons->rx_msg_lock);
-       ret |= !list_empty(&cons->rx_msg_list);
+       ret |= !list_empty(&cons->rx_msg_list) || cons->aborted;
        spin_unlock_irq(&cons->rx_msg_lock);
 
        return ret;
@@ -244,6 +246,12 @@ int ivpu_ipc_receive(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons,
                return -EAGAIN;
        }
        list_del(&rx_msg->link);
+       if (cons->aborted) {
+               spin_unlock_irq(&cons->rx_msg_lock);
+               ret = -ECANCELED;
+               goto out;
+       }
+
        spin_unlock_irq(&cons->rx_msg_lock);
 
        if (ipc_buf)
@@ -261,6 +269,7 @@ int ivpu_ipc_receive(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons,
        }
 
        ivpu_ipc_rx_mark_free(vdev, rx_msg->ipc_hdr, rx_msg->jsm_msg);
+out:
        atomic_dec(&ipc->rx_msg_count);
        kfree(rx_msg);
 
@@ -522,8 +531,12 @@ void ivpu_ipc_disable(struct ivpu_device *vdev)
        mutex_unlock(&ipc->lock);
 
        spin_lock_irqsave(&ipc->cons_list_lock, flags);
-       list_for_each_entry_safe(cons, c, &ipc->cons_list, link)
+       list_for_each_entry_safe(cons, c, &ipc->cons_list, link) {
+               spin_lock(&cons->rx_msg_lock);
+               cons->aborted = true;
+               spin_unlock(&cons->rx_msg_lock);
                wake_up(&cons->rx_msg_wq);
+       }
        spin_unlock_irqrestore(&ipc->cons_list_lock, flags);
 }
 
@@ -532,6 +545,7 @@ void ivpu_ipc_reset(struct ivpu_device *vdev)
        struct ivpu_ipc_info *ipc = vdev->ipc;
 
        mutex_lock(&ipc->lock);
+       drm_WARN_ON(&vdev->drm, ipc->on);
 
        memset(ivpu_bo_vaddr(ipc->mem_tx), 0, ivpu_bo_size(ipc->mem_tx));
        memset(ivpu_bo_vaddr(ipc->mem_rx), 0, ivpu_bo_size(ipc->mem_rx));
index 6918db23daa4bc8130a55be3cff68a22b7edd172..a380787f7222ac66ce318f0cf8e41fa1b10540c0 100644 (file)
@@ -47,8 +47,9 @@ struct ivpu_ipc_consumer {
        u32 channel;
        u32 tx_vpu_addr;
        u32 request_id;
+       bool aborted;
 
-       spinlock_t rx_msg_lock; /* Protects rx_msg_list */
+       spinlock_t rx_msg_lock; /* Protects rx_msg_list and aborted */
        struct list_head rx_msg_list;
        wait_queue_head_t rx_msg_wq;
 };
index a245b2d44db77a65f5ea57f750fd5ab5c41cc9d9..15a408fad49450bf5a7c47fa7402622ff99e4916 100644 (file)
@@ -578,6 +578,7 @@ static int ivpu_job_done_thread(void *arg)
        ivpu_ipc_consumer_add(vdev, &cons, VPU_IPC_CHAN_JOB_RET);
 
        while (!kthread_should_stop()) {
+               cons.aborted = false;
                timeout = ivpu_tdr_timeout_ms ? ivpu_tdr_timeout_ms : vdev->timeout.tdr;
                jobs_submitted = !xa_empty(&vdev->submitted_jobs_xa);
                ret = ivpu_ipc_receive(vdev, &cons, NULL, &jsm_msg, timeout);