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

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
Loading
Loading
Loading
Loading
+17 −2
Original line number Diff line number Diff line
@@ -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;
@@ -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)
+6 −3
Original line number Diff line number Diff line
@@ -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
@@ -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);
}
@@ -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;
+10 −3
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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)
+4 −4
Original line number Diff line number Diff line
@@ -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;

@@ -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");
@@ -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;

@@ -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");
+2 −2
Original line number Diff line number Diff line
@@ -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);
Loading