Commit 2f7ffb06 authored by Jacek Lawrynowicz's avatar Jacek Lawrynowicz

accel/ivpu: Replace wake_thread with kfifo

Use kfifo to pass IRQ sources to IRQ thread so it will be possible to
use IRQ thread by multiple IRQ types.
Signed-off-by: default avatarJacek Lawrynowicz <jacek.lawrynowicz@linux.intel.com>
Reviewed-by: default avatarWachowski, Karol <karol.wachowski@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240515113006.457472-4-jacek.lawrynowicz@linux.intel.com
parent 8a27ad81
...@@ -320,7 +320,7 @@ static int ivpu_wait_for_ready(struct ivpu_device *vdev) ...@@ -320,7 +320,7 @@ static int ivpu_wait_for_ready(struct ivpu_device *vdev)
timeout = jiffies + msecs_to_jiffies(vdev->timeout.boot); timeout = jiffies + msecs_to_jiffies(vdev->timeout.boot);
while (1) { while (1) {
ivpu_ipc_irq_handler(vdev, NULL); ivpu_ipc_irq_handler(vdev);
ret = ivpu_ipc_receive(vdev, &cons, &ipc_hdr, NULL, 0); ret = ivpu_ipc_receive(vdev, &cons, &ipc_hdr, NULL, 0);
if (ret != -ETIMEDOUT || time_after_eq(jiffies, timeout)) if (ret != -ETIMEDOUT || time_after_eq(jiffies, timeout))
break; break;
...@@ -449,8 +449,23 @@ static const struct drm_driver driver = { ...@@ -449,8 +449,23 @@ static const struct drm_driver driver = {
static irqreturn_t ivpu_irq_thread_handler(int irq, void *arg) static irqreturn_t ivpu_irq_thread_handler(int irq, void *arg)
{ {
struct ivpu_device *vdev = arg; struct ivpu_device *vdev = arg;
u8 irq_src;
return ivpu_ipc_irq_thread_handler(vdev); if (kfifo_is_empty(&vdev->hw->irq.fifo))
return IRQ_NONE;
while (kfifo_get(&vdev->hw->irq.fifo, &irq_src)) {
switch (irq_src) {
case IVPU_HW_IRQ_SRC_IPC:
ivpu_ipc_irq_thread_handler(vdev);
break;
default:
ivpu_err_ratelimited(vdev, "Unknown IRQ source: %u\n", irq_src);
break;
}
}
return IRQ_HANDLED;
} }
static int ivpu_irq_init(struct ivpu_device *vdev) static int ivpu_irq_init(struct ivpu_device *vdev)
......
...@@ -263,6 +263,8 @@ void ivpu_hw_profiling_freq_drive(struct ivpu_device *vdev, bool enable) ...@@ -263,6 +263,8 @@ void ivpu_hw_profiling_freq_drive(struct ivpu_device *vdev, bool enable)
void ivpu_irq_handlers_init(struct ivpu_device *vdev) void ivpu_irq_handlers_init(struct ivpu_device *vdev)
{ {
INIT_KFIFO(vdev->hw->irq.fifo);
if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX)
vdev->hw->irq.ip_irq_handler = ivpu_hw_ip_irq_handler_37xx; vdev->hw->irq.ip_irq_handler = ivpu_hw_ip_irq_handler_37xx;
else else
...@@ -276,6 +278,7 @@ void ivpu_irq_handlers_init(struct ivpu_device *vdev) ...@@ -276,6 +278,7 @@ void ivpu_irq_handlers_init(struct ivpu_device *vdev)
void ivpu_hw_irq_enable(struct ivpu_device *vdev) void ivpu_hw_irq_enable(struct ivpu_device *vdev)
{ {
kfifo_reset(&vdev->hw->irq.fifo);
ivpu_hw_ip_irq_enable(vdev); ivpu_hw_ip_irq_enable(vdev);
ivpu_hw_btrs_irq_enable(vdev); ivpu_hw_btrs_irq_enable(vdev);
} }
...@@ -288,21 +291,21 @@ void ivpu_hw_irq_disable(struct ivpu_device *vdev) ...@@ -288,21 +291,21 @@ void ivpu_hw_irq_disable(struct ivpu_device *vdev)
irqreturn_t ivpu_hw_irq_handler(int irq, void *ptr) irqreturn_t ivpu_hw_irq_handler(int irq, void *ptr)
{ {
bool ip_handled, btrs_handled, wake_thread = false;
struct ivpu_device *vdev = ptr; struct ivpu_device *vdev = ptr;
bool ip_handled, btrs_handled;
ivpu_hw_btrs_global_int_disable(vdev); ivpu_hw_btrs_global_int_disable(vdev);
btrs_handled = ivpu_hw_btrs_irq_handler(vdev, irq); btrs_handled = ivpu_hw_btrs_irq_handler(vdev, irq);
if (!ivpu_hw_is_idle((vdev)) || !btrs_handled) if (!ivpu_hw_is_idle((vdev)) || !btrs_handled)
ip_handled = ivpu_hw_ip_irq_handler(vdev, irq, &wake_thread); ip_handled = ivpu_hw_ip_irq_handler(vdev, irq);
else else
ip_handled = false; ip_handled = false;
/* Re-enable global interrupts to re-trigger MSI for pending interrupts */ /* Re-enable global interrupts to re-trigger MSI for pending interrupts */
ivpu_hw_btrs_global_int_enable(vdev); ivpu_hw_btrs_global_int_enable(vdev);
if (wake_thread) if (!kfifo_is_empty(&vdev->hw->irq.fifo))
return IRQ_WAKE_THREAD; return IRQ_WAKE_THREAD;
if (ip_handled || btrs_handled) if (ip_handled || btrs_handled)
return IRQ_HANDLED; return IRQ_HANDLED;
......
...@@ -6,10 +6,16 @@ ...@@ -6,10 +6,16 @@
#ifndef __IVPU_HW_H__ #ifndef __IVPU_HW_H__
#define __IVPU_HW_H__ #define __IVPU_HW_H__
#include <linux/kfifo.h>
#include "ivpu_drv.h" #include "ivpu_drv.h"
#include "ivpu_hw_btrs.h" #include "ivpu_hw_btrs.h"
#include "ivpu_hw_ip.h" #include "ivpu_hw_ip.h"
#define IVPU_HW_IRQ_FIFO_LENGTH 1024
#define IVPU_HW_IRQ_SRC_IPC 1
struct ivpu_addr_range { struct ivpu_addr_range {
resource_size_t start; resource_size_t start;
resource_size_t end; resource_size_t end;
...@@ -18,7 +24,8 @@ struct ivpu_addr_range { ...@@ -18,7 +24,8 @@ struct ivpu_addr_range {
struct ivpu_hw_info { struct ivpu_hw_info {
struct { struct {
bool (*btrs_irq_handler)(struct ivpu_device *vdev, int irq); bool (*btrs_irq_handler)(struct ivpu_device *vdev, int irq);
bool (*ip_irq_handler)(struct ivpu_device *vdev, int irq, bool *wake_thread); bool (*ip_irq_handler)(struct ivpu_device *vdev, int irq);
DECLARE_KFIFO(fifo, u8, IVPU_HW_IRQ_FIFO_LENGTH);
} irq; } irq;
struct { struct {
struct ivpu_addr_range global; struct ivpu_addr_range global;
...@@ -61,9 +68,9 @@ static inline u32 ivpu_hw_btrs_irq_handler(struct ivpu_device *vdev, int irq) ...@@ -61,9 +68,9 @@ static inline u32 ivpu_hw_btrs_irq_handler(struct ivpu_device *vdev, int irq)
return vdev->hw->irq.btrs_irq_handler(vdev, irq); return vdev->hw->irq.btrs_irq_handler(vdev, irq);
} }
static inline u32 ivpu_hw_ip_irq_handler(struct ivpu_device *vdev, int irq, bool *wake_thread) static inline u32 ivpu_hw_ip_irq_handler(struct ivpu_device *vdev, int irq)
{ {
return vdev->hw->irq.ip_irq_handler(vdev, irq, wake_thread); return vdev->hw->irq.ip_irq_handler(vdev, irq);
} }
static inline void ivpu_hw_range_init(struct ivpu_addr_range *range, u64 start, u64 size) static inline void ivpu_hw_range_init(struct ivpu_addr_range *range, u64 start, u64 size)
......
...@@ -1066,7 +1066,7 @@ static void irq_noc_firewall_handler(struct ivpu_device *vdev) ...@@ -1066,7 +1066,7 @@ static void irq_noc_firewall_handler(struct ivpu_device *vdev)
} }
/* Handler for IRQs from NPU core */ /* Handler for IRQs from NPU core */
bool ivpu_hw_ip_irq_handler_37xx(struct ivpu_device *vdev, int irq, bool *wake_thread) bool ivpu_hw_ip_irq_handler_37xx(struct ivpu_device *vdev, int irq)
{ {
u32 status = REGV_RD32(VPU_37XX_HOST_SS_ICB_STATUS_0) & ICB_0_IRQ_MASK_37XX; u32 status = REGV_RD32(VPU_37XX_HOST_SS_ICB_STATUS_0) & ICB_0_IRQ_MASK_37XX;
...@@ -1079,7 +1079,7 @@ bool ivpu_hw_ip_irq_handler_37xx(struct ivpu_device *vdev, int irq, bool *wake_t ...@@ -1079,7 +1079,7 @@ bool ivpu_hw_ip_irq_handler_37xx(struct ivpu_device *vdev, int irq, bool *wake_t
ivpu_mmu_irq_evtq_handler(vdev); ivpu_mmu_irq_evtq_handler(vdev);
if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, HOST_IPC_FIFO_INT, status)) if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, HOST_IPC_FIFO_INT, status))
ivpu_ipc_irq_handler(vdev, wake_thread); ivpu_ipc_irq_handler(vdev);
if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_1_INT, status)) if (REG_TEST_FLD(VPU_37XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_1_INT, status))
ivpu_dbg(vdev, IRQ, "MMU sync complete\n"); ivpu_dbg(vdev, IRQ, "MMU sync complete\n");
...@@ -1100,7 +1100,7 @@ bool ivpu_hw_ip_irq_handler_37xx(struct ivpu_device *vdev, int irq, bool *wake_t ...@@ -1100,7 +1100,7 @@ bool ivpu_hw_ip_irq_handler_37xx(struct ivpu_device *vdev, int irq, bool *wake_t
} }
/* Handler for IRQs from NPU core */ /* Handler for IRQs from NPU core */
bool ivpu_hw_ip_irq_handler_40xx(struct ivpu_device *vdev, int irq, bool *wake_thread) bool ivpu_hw_ip_irq_handler_40xx(struct ivpu_device *vdev, int irq)
{ {
u32 status = REGV_RD32(VPU_40XX_HOST_SS_ICB_STATUS_0) & ICB_0_IRQ_MASK_40XX; u32 status = REGV_RD32(VPU_40XX_HOST_SS_ICB_STATUS_0) & ICB_0_IRQ_MASK_40XX;
...@@ -1113,7 +1113,7 @@ bool ivpu_hw_ip_irq_handler_40xx(struct ivpu_device *vdev, int irq, bool *wake_t ...@@ -1113,7 +1113,7 @@ bool ivpu_hw_ip_irq_handler_40xx(struct ivpu_device *vdev, int irq, bool *wake_t
ivpu_mmu_irq_evtq_handler(vdev); ivpu_mmu_irq_evtq_handler(vdev);
if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, HOST_IPC_FIFO_INT, status)) if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, HOST_IPC_FIFO_INT, status))
ivpu_ipc_irq_handler(vdev, wake_thread); ivpu_ipc_irq_handler(vdev);
if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_1_INT, status)) if (REG_TEST_FLD(VPU_40XX_HOST_SS_ICB_STATUS_0, MMU_IRQ_1_INT, status))
ivpu_dbg(vdev, IRQ, "MMU sync complete\n"); ivpu_dbg(vdev, IRQ, "MMU sync complete\n");
......
...@@ -22,8 +22,8 @@ void ivpu_hw_ip_wdt_disable(struct ivpu_device *vdev); ...@@ -22,8 +22,8 @@ void ivpu_hw_ip_wdt_disable(struct ivpu_device *vdev);
void ivpu_hw_ip_diagnose_failure(struct ivpu_device *vdev); void ivpu_hw_ip_diagnose_failure(struct ivpu_device *vdev);
u32 ivpu_hw_ip_ipc_rx_count_get(struct ivpu_device *vdev); u32 ivpu_hw_ip_ipc_rx_count_get(struct ivpu_device *vdev);
void ivpu_hw_ip_irq_clear(struct ivpu_device *vdev); void ivpu_hw_ip_irq_clear(struct ivpu_device *vdev);
bool ivpu_hw_ip_irq_handler_37xx(struct ivpu_device *vdev, int irq, bool *wake_thread); bool ivpu_hw_ip_irq_handler_37xx(struct ivpu_device *vdev, int irq);
bool ivpu_hw_ip_irq_handler_40xx(struct ivpu_device *vdev, int irq, bool *wake_thread); bool ivpu_hw_ip_irq_handler_40xx(struct ivpu_device *vdev, int irq);
void ivpu_hw_ip_db_set(struct ivpu_device *vdev, u32 db_id); void ivpu_hw_ip_db_set(struct ivpu_device *vdev, u32 db_id);
u32 ivpu_hw_ip_ipc_rx_addr_get(struct ivpu_device *vdev); u32 ivpu_hw_ip_ipc_rx_addr_get(struct ivpu_device *vdev);
void ivpu_hw_ip_ipc_tx_set(struct ivpu_device *vdev, u32 vpu_addr); void ivpu_hw_ip_ipc_tx_set(struct ivpu_device *vdev, u32 vpu_addr);
......
...@@ -378,7 +378,7 @@ ivpu_ipc_match_consumer(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons ...@@ -378,7 +378,7 @@ ivpu_ipc_match_consumer(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons
return false; return false;
} }
void ivpu_ipc_irq_handler(struct ivpu_device *vdev, bool *wake_thread) void ivpu_ipc_irq_handler(struct ivpu_device *vdev)
{ {
struct ivpu_ipc_info *ipc = vdev->ipc; struct ivpu_ipc_info *ipc = vdev->ipc;
struct ivpu_ipc_consumer *cons; struct ivpu_ipc_consumer *cons;
...@@ -442,11 +442,12 @@ void ivpu_ipc_irq_handler(struct ivpu_device *vdev, bool *wake_thread) ...@@ -442,11 +442,12 @@ void ivpu_ipc_irq_handler(struct ivpu_device *vdev, bool *wake_thread)
} }
} }
if (wake_thread) if (!list_empty(&ipc->cb_msg_list))
*wake_thread = !list_empty(&ipc->cb_msg_list); if (!kfifo_put(&vdev->hw->irq.fifo, IVPU_HW_IRQ_SRC_IPC))
ivpu_err_ratelimited(vdev, "IRQ FIFO full\n");
} }
irqreturn_t ivpu_ipc_irq_thread_handler(struct ivpu_device *vdev) void ivpu_ipc_irq_thread_handler(struct ivpu_device *vdev)
{ {
struct ivpu_ipc_info *ipc = vdev->ipc; struct ivpu_ipc_info *ipc = vdev->ipc;
struct ivpu_ipc_rx_msg *rx_msg, *r; struct ivpu_ipc_rx_msg *rx_msg, *r;
...@@ -462,8 +463,6 @@ irqreturn_t ivpu_ipc_irq_thread_handler(struct ivpu_device *vdev) ...@@ -462,8 +463,6 @@ irqreturn_t ivpu_ipc_irq_thread_handler(struct ivpu_device *vdev)
rx_msg->callback(vdev, rx_msg->ipc_hdr, rx_msg->jsm_msg); rx_msg->callback(vdev, rx_msg->ipc_hdr, rx_msg->jsm_msg);
ivpu_ipc_rx_msg_del(vdev, rx_msg); ivpu_ipc_rx_msg_del(vdev, rx_msg);
} }
return IRQ_HANDLED;
} }
int ivpu_ipc_init(struct ivpu_device *vdev) int ivpu_ipc_init(struct ivpu_device *vdev)
......
...@@ -89,8 +89,8 @@ void ivpu_ipc_enable(struct ivpu_device *vdev); ...@@ -89,8 +89,8 @@ void ivpu_ipc_enable(struct ivpu_device *vdev);
void ivpu_ipc_disable(struct ivpu_device *vdev); void ivpu_ipc_disable(struct ivpu_device *vdev);
void ivpu_ipc_reset(struct ivpu_device *vdev); void ivpu_ipc_reset(struct ivpu_device *vdev);
void ivpu_ipc_irq_handler(struct ivpu_device *vdev, bool *wake_thread); void ivpu_ipc_irq_handler(struct ivpu_device *vdev);
irqreturn_t ivpu_ipc_irq_thread_handler(struct ivpu_device *vdev); void ivpu_ipc_irq_thread_handler(struct ivpu_device *vdev);
void ivpu_ipc_consumer_add(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons, void ivpu_ipc_consumer_add(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons,
u32 channel, ivpu_ipc_rx_callback_t callback); u32 channel, ivpu_ipc_rx_callback_t callback);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment