habanalabs: add support for common decoder interrupts
authorOfir Bitton <obitton@habana.ai>
Tue, 28 Jun 2022 15:34:58 +0000 (18:34 +0300)
committerOded Gabbay <ogabbay@kernel.org>
Tue, 12 Jul 2022 06:09:29 +0000 (09:09 +0300)
User application should be able to get notification for any decoder
completion. Hence, we introduce a new interface in which a user
can wait for all current decoder pending interrupts.

Signed-off-by: Ofir Bitton <obitton@habana.ai>
Reviewed-by: Oded Gabbay <ogabbay@kernel.org>
Signed-off-by: Oded Gabbay <ogabbay@kernel.org>
drivers/misc/habanalabs/common/command_submission.c
drivers/misc/habanalabs/common/habanalabs.h
drivers/misc/habanalabs/common/irq.c
drivers/misc/habanalabs/gaudi2/gaudi2.c
include/uapi/misc/habanalabs.h

index 275dcb6..eb5f1ae 100644 (file)
@@ -1082,6 +1082,9 @@ void hl_release_pending_user_interrupts(struct hl_device *hdev)
 
        interrupt = &hdev->common_user_cq_interrupt;
        wake_pending_user_interrupt_threads(interrupt);
+
+       interrupt = &hdev->common_decoder_interrupt;
+       wake_pending_user_interrupt_threads(interrupt);
 }
 
 static void job_wq_completion(struct work_struct *work)
@@ -3375,6 +3378,8 @@ static int hl_interrupt_wait_ioctl(struct hl_fpriv *hpriv, void *data)
 
        } else if (interrupt_id == HL_COMMON_USER_CQ_INTERRUPT_ID) {
                interrupt = &hdev->common_user_cq_interrupt;
+       } else if (interrupt_id == HL_COMMON_DEC_INTERRUPT_ID) {
+               interrupt = &hdev->common_decoder_interrupt;
        } else {
                dev_err(hdev->dev, "invalid user interrupt %u", interrupt_id);
                return -EINVAL;
index 9b2451f..7e84f2c 100644 (file)
@@ -77,6 +77,7 @@ struct hl_fpriv;
 #define HL_INVALID_QUEUE               UINT_MAX
 
 #define HL_COMMON_USER_CQ_INTERRUPT_ID 0xFFF
+#define HL_COMMON_DEC_INTERRUPT_ID     0xFFE
 
 #define HL_STATE_DUMP_HIST_LEN         5
 
@@ -2955,6 +2956,7 @@ struct hl_reset_info {
  * @common_user_cq_interrupt: common user CQ interrupt for all user CQ interrupts.
  *                         upon any user CQ interrupt, driver will monitor the
  *                         list of fences registered to this common structure.
+ * @common_decoder_interrupt: common decoder interrupt for all user decoder interrupts.
  * @shadow_cs_queue: pointer to a shadow queue that holds pointers to
  *                   outstanding command submissions.
  * @cq_wq: work queues of completion queues for executing work in process
@@ -3119,6 +3121,7 @@ struct hl_device {
        struct hl_cq                    *completion_queue;
        struct hl_user_interrupt        *user_interrupt;
        struct hl_user_interrupt        common_user_cq_interrupt;
+       struct hl_user_interrupt        common_decoder_interrupt;
        struct hl_cs                    **shadow_cs_queue;
        struct workqueue_struct         **cq_wq;
        struct workqueue_struct         *eq_wq;
index fd8f2bd..d60dafb 100644 (file)
@@ -333,12 +333,9 @@ irqreturn_t hl_irq_handler_user_interrupt(int irq, void *arg)
        struct hl_user_interrupt *user_int = arg;
        struct hl_device *hdev = user_int->hdev;
 
-       /* If the interrupt is not a decoder interrupt, it means the interrupt
-        * belongs to a user cq. In that case, before handling it, we need to handle the common
-        * user cq
-        */
-       if (!user_int->is_decoder)
-               /* Handle user cq interrupts registered on all interrupts */
+       if (user_int->is_decoder)
+               handle_user_interrupt(hdev, &hdev->common_decoder_interrupt);
+       else
                handle_user_interrupt(hdev, &hdev->common_user_cq_interrupt);
 
        /* Handle user cq or decoder interrupts registered on this specific irq */
index 8f01207..83da424 100644 (file)
@@ -2895,6 +2895,10 @@ static void gaudi2_user_interrupt_setup(struct hl_device *hdev)
        HL_USR_INTR_STRUCT_INIT(hdev->common_user_cq_interrupt, hdev,
                                HL_COMMON_USER_CQ_INTERRUPT_ID, false);
 
+       /* Initialize common decoder interrupt */
+       HL_USR_INTR_STRUCT_INIT(hdev->common_decoder_interrupt, hdev,
+                               HL_COMMON_DEC_INTERRUPT_ID, true);
+
        /* User interrupts structure holds both decoder and user interrupts from various engines.
         * We first initialize the decoder interrupts and then we add the user interrupts.
         * The only limitation is that the last decoder interrupt id must be smaller
index 4ee24a3..8c6ab71 100644 (file)
@@ -1443,6 +1443,7 @@ union hl_cs_args {
 #define HL_WAIT_CS_FLAGS_INTERRUPT             0x2
 #define HL_WAIT_CS_FLAGS_INTERRUPT_MASK                0xFFF00000
 #define HL_WAIT_CS_FLAGS_ANY_CQ_INTERRUPT      0xFFF00000
+#define HL_WAIT_CS_FLAGS_ANY_DEC_INTERRUPT     0xFFE00000
 #define HL_WAIT_CS_FLAGS_MULTI_CS              0x4
 #define HL_WAIT_CS_FLAGS_INTERRUPT_KERNEL_CQ   0x10
 #define HL_WAIT_CS_FLAGS_REGISTER_INTERRUPT    0x20
@@ -1496,6 +1497,9 @@ struct hl_wait_cs_in {
         *
         * in order to wait for any CQ interrupt, set interrupt value to
         * HL_WAIT_CS_FLAGS_ANY_CQ_INTERRUPT.
+        *
+        * in order to wait for any decoder interrupt, set interrupt value to
+        * HL_WAIT_CS_FLAGS_ANY_DEC_INTERRUPT.
         */
        __u32 flags;