Skip to content

Commit

Permalink
accel/ivpu: Replace wake_thread with kfifo
Browse files Browse the repository at this point in the history
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: Jacek Lawrynowicz <jacek.lawrynowicz@linux.intel.com>
Reviewed-by: Wachowski, Karol <karol.wachowski@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240515113006.457472-4-jacek.lawrynowicz@linux.intel.com
  • Loading branch information
jlawryno committed May 17, 2024
1 parent 8a27ad8 commit 2f7ffb0
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 22 deletions.
19 changes: 17 additions & 2 deletions drivers/accel/ivpu/ivpu_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ static int ivpu_wait_for_ready(struct ivpu_device *vdev)

timeout = jiffies + msecs_to_jiffies(vdev->timeout.boot);
while (1) {
ivpu_ipc_irq_handler(vdev, NULL);
ivpu_ipc_irq_handler(vdev);
ret = ivpu_ipc_receive(vdev, &cons, &ipc_hdr, NULL, 0);
if (ret != -ETIMEDOUT || time_after_eq(jiffies, timeout))
break;
Expand Down Expand Up @@ -449,8 +449,23 @@ static const struct drm_driver driver = {
static irqreturn_t ivpu_irq_thread_handler(int irq, void *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)
Expand Down
9 changes: 6 additions & 3 deletions drivers/accel/ivpu/ivpu_hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
INIT_KFIFO(vdev->hw->irq.fifo);

if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX)
vdev->hw->irq.ip_irq_handler = ivpu_hw_ip_irq_handler_37xx;
else
Expand All @@ -276,6 +278,7 @@ void ivpu_irq_handlers_init(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_btrs_irq_enable(vdev);
}
Expand All @@ -288,21 +291,21 @@ void ivpu_hw_irq_disable(struct ivpu_device *vdev)

irqreturn_t ivpu_hw_irq_handler(int irq, void *ptr)
{
bool ip_handled, btrs_handled, wake_thread = false;
struct ivpu_device *vdev = ptr;
bool ip_handled, btrs_handled;

ivpu_hw_btrs_global_int_disable(vdev);

btrs_handled = ivpu_hw_btrs_irq_handler(vdev, irq);
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
ip_handled = false;

/* Re-enable global interrupts to re-trigger MSI for pending interrupts */
ivpu_hw_btrs_global_int_enable(vdev);

if (wake_thread)
if (!kfifo_is_empty(&vdev->hw->irq.fifo))
return IRQ_WAKE_THREAD;
if (ip_handled || btrs_handled)
return IRQ_HANDLED;
Expand Down
13 changes: 10 additions & 3 deletions drivers/accel/ivpu/ivpu_hw.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,16 @@
#ifndef __IVPU_HW_H__
#define __IVPU_HW_H__

#include <linux/kfifo.h>

#include "ivpu_drv.h"
#include "ivpu_hw_btrs.h"
#include "ivpu_hw_ip.h"

#define IVPU_HW_IRQ_FIFO_LENGTH 1024

#define IVPU_HW_IRQ_SRC_IPC 1

struct ivpu_addr_range {
resource_size_t start;
resource_size_t end;
Expand All @@ -18,7 +24,8 @@ struct ivpu_addr_range {
struct ivpu_hw_info {
struct {
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;
struct {
struct ivpu_addr_range global;
Expand Down Expand Up @@ -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);
}

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)
Expand Down
8 changes: 4 additions & 4 deletions drivers/accel/ivpu/ivpu_hw_ip.c
Original file line number Diff line number Diff line change
Expand Up @@ -1066,7 +1066,7 @@ static void irq_noc_firewall_handler(struct ivpu_device *vdev)
}

/* 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;

Expand All @@ -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);

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))
ivpu_dbg(vdev, IRQ, "MMU sync complete\n");
Expand All @@ -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 */
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;

Expand All @@ -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);

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))
ivpu_dbg(vdev, IRQ, "MMU sync complete\n");
Expand Down
4 changes: 2 additions & 2 deletions drivers/accel/ivpu/ivpu_hw_ip.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ void ivpu_hw_ip_wdt_disable(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);
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_40xx(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);
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);
void ivpu_hw_ip_ipc_tx_set(struct ivpu_device *vdev, u32 vpu_addr);
Expand Down
11 changes: 5 additions & 6 deletions drivers/accel/ivpu/ivpu_ipc.c
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ ivpu_ipc_match_consumer(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons
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_consumer *cons;
Expand Down Expand Up @@ -442,11 +442,12 @@ void ivpu_ipc_irq_handler(struct ivpu_device *vdev, bool *wake_thread)
}
}

if (wake_thread)
*wake_thread = !list_empty(&ipc->cb_msg_list);
if (!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_rx_msg *rx_msg, *r;
Expand All @@ -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);
ivpu_ipc_rx_msg_del(vdev, rx_msg);
}

return IRQ_HANDLED;
}

int ivpu_ipc_init(struct ivpu_device *vdev)
Expand Down
4 changes: 2 additions & 2 deletions drivers/accel/ivpu/ivpu_ipc.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ void ivpu_ipc_enable(struct ivpu_device *vdev);
void ivpu_ipc_disable(struct ivpu_device *vdev);
void ivpu_ipc_reset(struct ivpu_device *vdev);

void ivpu_ipc_irq_handler(struct ivpu_device *vdev, bool *wake_thread);
irqreturn_t ivpu_ipc_irq_thread_handler(struct ivpu_device *vdev);
void ivpu_ipc_irq_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,
u32 channel, ivpu_ipc_rx_callback_t callback);
Expand Down

0 comments on commit 2f7ffb0

Please sign in to comment.