wake_pending_user_interrupt_threads(struct hl_user_interrupt *interrupt)
 {
        struct hl_user_pending_interrupt *pend, *temp;
-       unsigned long flags;
 
-       spin_lock_irqsave(&interrupt->wait_list_lock, flags);
+       spin_lock(&interrupt->wait_list_lock);
        list_for_each_entry_safe(pend, temp, &interrupt->wait_list_head, wait_list_node) {
                if (pend->ts_reg_info.buf) {
                        list_del(&pend->wait_list_node);
                        complete_all(&pend->fence.completion);
                }
        }
-       spin_unlock_irqrestore(&interrupt->wait_list_lock, flags);
+       spin_unlock(&interrupt->wait_list_lock);
 }
 
 void hl_release_pending_user_interrupts(struct hl_device *hdev)
        struct hl_user_pending_interrupt *cb_last =
                        (struct hl_user_pending_interrupt *)ts_buff->kernel_buff_address +
                        (ts_buff->kernel_buff_size / sizeof(struct hl_user_pending_interrupt));
-       unsigned long flags, iter_counter = 0;
+       unsigned long iter_counter = 0;
        u64 current_cq_counter;
        ktime_t timestamp;
 
        timestamp = ktime_get();
 
 start_over:
-       spin_lock_irqsave(wait_list_lock, flags);
+       spin_lock(wait_list_lock);
 
        /* Unregister only if we didn't reach the target value
         * since in this case there will be no handling in irq context
                current_cq_counter = *requested_offset_record->cq_kernel_addr;
                if (current_cq_counter < requested_offset_record->cq_target_value) {
                        list_del(&requested_offset_record->wait_list_node);
-                       spin_unlock_irqrestore(wait_list_lock, flags);
+                       spin_unlock(wait_list_lock);
 
                        hl_mmap_mem_buf_put(requested_offset_record->ts_reg_info.buf);
                        hl_cb_put(requested_offset_record->ts_reg_info.cq_cb);
                        dev_dbg(buf->mmg->dev,
                                "ts node in middle of irq handling\n");
 
-                       /* irq handling in the middle give it time to finish */
-                       spin_unlock_irqrestore(wait_list_lock, flags);
+                       /* irq thread handling in the middle give it time to finish */
+                       spin_unlock(wait_list_lock);
                        usleep_range(100, 1000);
                        if (++iter_counter == MAX_TS_ITER_NUM) {
                                dev_err(buf->mmg->dev,
                                (u64 *) cq_cb->kernel_address + cq_offset;
                requested_offset_record->cq_target_value = target_value;
 
-               spin_unlock_irqrestore(wait_list_lock, flags);
+               spin_unlock(wait_list_lock);
        }
 
        *pend = requested_offset_record;
        struct hl_user_pending_interrupt *pend;
        struct hl_mmap_mem_buf *buf;
        struct hl_cb *cq_cb;
-       unsigned long timeout, flags;
+       unsigned long timeout;
        long completion_rc;
        int rc = 0;
 
                pend->cq_target_value = target_value;
        }
 
-       spin_lock_irqsave(&interrupt->wait_list_lock, flags);
+       spin_lock(&interrupt->wait_list_lock);
 
        /* We check for completion value as interrupt could have been received
         * before we added the node to the wait list
        if (*pend->cq_kernel_addr >= target_value) {
                if (register_ts_record)
                        pend->ts_reg_info.in_use = 0;
-               spin_unlock_irqrestore(&interrupt->wait_list_lock, flags);
+               spin_unlock(&interrupt->wait_list_lock);
 
                *status = HL_WAIT_CS_STATUS_COMPLETED;
 
                        goto set_timestamp;
                }
        } else if (!timeout_us) {
-               spin_unlock_irqrestore(&interrupt->wait_list_lock, flags);
+               spin_unlock(&interrupt->wait_list_lock);
                *status = HL_WAIT_CS_STATUS_BUSY;
                pend->fence.timestamp = ktime_get();
                goto set_timestamp;
                pend->ts_reg_info.in_use = 1;
 
        list_add_tail(&pend->wait_list_node, &interrupt->wait_list_head);
-       spin_unlock_irqrestore(&interrupt->wait_list_lock, flags);
+       spin_unlock(&interrupt->wait_list_lock);
 
        if (register_ts_record) {
                rc = *status = HL_WAIT_CS_STATUS_COMPLETED;
         * for ts record, the node will be deleted in the irq handler after
         * we reach the target value.
         */
-       spin_lock_irqsave(&interrupt->wait_list_lock, flags);
+       spin_lock(&interrupt->wait_list_lock);
        list_del(&pend->wait_list_node);
-       spin_unlock_irqrestore(&interrupt->wait_list_lock, flags);
+       spin_unlock(&interrupt->wait_list_lock);
 
 set_timestamp:
        *timestamp = ktime_to_ns(pend->fence.timestamp);
                                u64 *timestamp)
 {
        struct hl_user_pending_interrupt *pend;
-       unsigned long timeout, flags;
+       unsigned long timeout;
        u64 completion_value;
        long completion_rc;
        int rc = 0;
        /* Add pending user interrupt to relevant list for the interrupt
         * handler to monitor
         */
-       spin_lock_irqsave(&interrupt->wait_list_lock, flags);
+       spin_lock(&interrupt->wait_list_lock);
        list_add_tail(&pend->wait_list_node, &interrupt->wait_list_head);
-       spin_unlock_irqrestore(&interrupt->wait_list_lock, flags);
+       spin_unlock(&interrupt->wait_list_lock);
 
        /* We check for completion value as interrupt could have been received
         * before we added the node to the wait list
         * If comparison fails, keep waiting until timeout expires
         */
        if (completion_rc > 0) {
-               spin_lock_irqsave(&interrupt->wait_list_lock, flags);
+               spin_lock(&interrupt->wait_list_lock);
                /* reinit_completion must be called before we check for user
                 * completion value, otherwise, if interrupt is received after
                 * the comparison and before the next wait_for_completion,
                 * we will reach timeout and fail
                 */
                reinit_completion(&pend->fence.completion);
-               spin_unlock_irqrestore(&interrupt->wait_list_lock, flags);
+               spin_unlock(&interrupt->wait_list_lock);
 
                if (copy_from_user(&completion_value, u64_to_user_ptr(user_address), 8)) {
                        dev_err(hdev->dev, "Failed to copy completion value from user\n");
        }
 
 remove_pending_user_interrupt:
-       spin_lock_irqsave(&interrupt->wait_list_lock, flags);
+       spin_lock(&interrupt->wait_list_lock);
        list_del(&pend->wait_list_node);
-       spin_unlock_irqrestore(&interrupt->wait_list_lock, flags);
+       spin_unlock(&interrupt->wait_list_lock);
 
        *timestamp = ktime_to_ns(pend->fence.timestamp);
 
 
 static int gaudi2_dec_enable_msix(struct hl_device *hdev)
 {
        int rc, i, irq_init_cnt, irq, relative_idx;
-       irq_handler_t irq_handler;
        struct hl_dec *dec;
 
        for (i = GAUDI2_IRQ_NUM_DCORE0_DEC0_NRM, irq_init_cnt = 0;
                irq = pci_irq_vector(hdev->pdev, i);
                relative_idx = i - GAUDI2_IRQ_NUM_DCORE0_DEC0_NRM;
 
-               irq_handler = (relative_idx % 2) ?
-                               hl_irq_handler_dec_abnrm :
-                               hl_irq_handler_user_interrupt;
-
-               dec = hdev->dec + relative_idx / 2;
-
                /* We pass different structures depending on the irq handler. For the abnormal
                 * interrupt we pass hl_dec and for the regular interrupt we pass the relevant
                 * user_interrupt entry
+                *
+                * TODO: change the dec abnrm to threaded irq
                 */
-               rc = request_irq(irq, irq_handler, 0, gaudi2_irq_name(i),
-                               ((relative_idx % 2) ?
-                               (void *) dec :
-                               (void *) &hdev->user_interrupt[dec->core_id]));
+
+               dec = hdev->dec + relative_idx / 2;
+               if (relative_idx % 2) {
+                       rc = request_irq(irq, hl_irq_handler_dec_abnrm, 0,
+                                               gaudi2_irq_name(i), (void *) dec);
+               } else {
+                       rc = request_threaded_irq(irq, hl_irq_handler_user_interrupt,
+                                       hl_irq_user_interrupt_thread_handler, IRQF_ONESHOT,
+                                       gaudi2_irq_name(i),
+                                       (void *) &hdev->user_interrupt[dec->core_id]);
+               }
+
                if (rc) {
                        dev_err(hdev->dev, "Failed to request IRQ %d", irq);
                        goto free_dec_irqs;
                irq = pci_irq_vector(hdev->pdev, i);
                irq_handler = hl_irq_handler_user_interrupt;
 
-               rc = request_irq(irq, irq_handler, 0, gaudi2_irq_name(i), &hdev->user_interrupt[j]);
+               rc = request_threaded_irq(irq, irq_handler, hl_irq_user_interrupt_thread_handler,
+                               IRQF_ONESHOT, gaudi2_irq_name(i), &hdev->user_interrupt[j]);
+
                if (rc) {
                        dev_err(hdev->dev, "Failed to request IRQ %d", irq);
                        goto free_user_irq;