Commit 852be13f authored by Jacek Lawrynowicz's avatar Jacek Lawrynowicz Committed by Daniel Vetter
Browse files

accel/ivpu: Add PM support

parent cd727221
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@ intel_vpu-y := \
	ivpu_job.o \
	ivpu_jsm_msg.o \
	ivpu_mmu.o \
	ivpu_mmu_context.o
	ivpu_mmu_context.o \
	ivpu_pm.o

obj-$(CONFIG_DRM_ACCEL_IVPU) += intel_vpu.o
 No newline at end of file
+28 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include "ivpu_jsm_msg.h"
#include "ivpu_mmu.h"
#include "ivpu_mmu_context.h"
#include "ivpu_pm.h"

#ifndef DRIVER_VERSION_STR
#define DRIVER_VERSION_STR __stringify(DRM_IVPU_DRIVER_MAJOR) "." \
@@ -462,6 +463,10 @@ static int ivpu_dev_init(struct ivpu_device *vdev)
	if (!vdev->ipc)
		return -ENOMEM;

	vdev->pm = drmm_kzalloc(&vdev->drm, sizeof(*vdev->pm), GFP_KERNEL);
	if (!vdev->pm)
		return -ENOMEM;

	vdev->hw->ops = &ivpu_hw_mtl_ops;
	vdev->platform = IVPU_PLATFORM_INVALID;
	vdev->context_xa_limit.min = IVPU_GLOBAL_CONTEXT_MMU_SSID + 1;
@@ -521,6 +526,12 @@ static int ivpu_dev_init(struct ivpu_device *vdev)
		goto err_fw_fini;
	}

	ret = ivpu_pm_init(vdev);
	if (ret) {
		ivpu_err(vdev, "Failed to initialize PM: %d\n", ret);
		goto err_ipc_fini;
	}

	ret = ivpu_job_done_thread_init(vdev);
	if (ret) {
		ivpu_err(vdev, "Failed to initialize job done thread: %d\n", ret);
@@ -539,6 +550,8 @@ static int ivpu_dev_init(struct ivpu_device *vdev)
		goto err_job_done_thread_fini;
	}

	ivpu_pm_enable(vdev);

	return 0;

err_job_done_thread_fini:
@@ -559,6 +572,7 @@ static int ivpu_dev_init(struct ivpu_device *vdev)

static void ivpu_dev_fini(struct ivpu_device *vdev)
{
	ivpu_pm_disable(vdev);
	ivpu_shutdown(vdev);
	ivpu_job_done_thread_fini(vdev);
	ivpu_ipc_fini(vdev);
@@ -611,11 +625,25 @@ static void ivpu_remove(struct pci_dev *pdev)
	ivpu_dev_fini(vdev);
}

static const struct dev_pm_ops ivpu_drv_pci_pm = {
	SET_SYSTEM_SLEEP_PM_OPS(ivpu_pm_suspend_cb, ivpu_pm_resume_cb)
	SET_RUNTIME_PM_OPS(ivpu_pm_runtime_suspend_cb, ivpu_pm_runtime_resume_cb, NULL)
};

static const struct pci_error_handlers ivpu_drv_pci_err = {
	.reset_prepare = ivpu_pm_reset_prepare_cb,
	.reset_done = ivpu_pm_reset_done_cb,
};

static struct pci_driver ivpu_pci_driver = {
	.name = KBUILD_MODNAME,
	.id_table = ivpu_pci_ids,
	.probe = ivpu_probe,
	.remove = ivpu_remove,
	.driver = {
		.pm = &ivpu_drv_pci_pm,
	},
	.err_handler = &ivpu_drv_pci_err,
};

module_pci_driver(ivpu_pci_driver);
+2 −0
Original line number Diff line number Diff line
@@ -76,6 +76,7 @@ struct ivpu_hw_info;
struct ivpu_mmu_info;
struct ivpu_fw_info;
struct ivpu_ipc_info;
struct ivpu_pm_info;

struct ivpu_device {
	struct drm_device drm;
@@ -89,6 +90,7 @@ struct ivpu_device {
	struct ivpu_mmu_info *mmu;
	struct ivpu_fw_info *fw;
	struct ivpu_ipc_info *ipc;
	struct ivpu_pm_info *pm;

	struct ivpu_mmu_context gctx;
	struct xarray context_xa;
+4 −0
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
#include "ivpu_gem.h"
#include "ivpu_hw.h"
#include "ivpu_ipc.h"
#include "ivpu_pm.h"

#define FW_GLOBAL_MEM_START	(2ull * SZ_1G)
#define FW_GLOBAL_MEM_END	(3ull * SZ_1G)
@@ -361,9 +362,12 @@ void ivpu_fw_boot_params_setup(struct ivpu_device *vdev, struct vpu_boot_params
	/* In case of warm boot we only have to reset the entrypoint addr */
	if (!ivpu_fw_is_cold_boot(vdev)) {
		boot_params->save_restore_ret_address = 0;
		vdev->pm->is_warmboot = true;
		return;
	}

	vdev->pm->is_warmboot = false;

	boot_params->magic = VPU_BOOT_PARAMS_MAGIC;
	boot_params->vpu_id = to_pci_dev(vdev->drm.dev)->bus->number;
	boot_params->frequency = ivpu_hw_reg_pll_freq_get(vdev);
+12 −0
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@
#include "ivpu_hw.h"
#include "ivpu_ipc.h"
#include "ivpu_mmu.h"
#include "ivpu_pm.h"

#define TILE_FUSE_ENABLE_BOTH	     0x0
#define TILE_FUSE_ENABLE_UPPER	     0x1
@@ -921,6 +922,8 @@ static void ivpu_hw_mtl_irq_disable(struct ivpu_device *vdev)
static void ivpu_hw_mtl_irq_wdt_nce_handler(struct ivpu_device *vdev)
{
	ivpu_err_ratelimited(vdev, "WDT NCE irq\n");

	ivpu_pm_schedule_recovery(vdev);
}

static void ivpu_hw_mtl_irq_wdt_mss_handler(struct ivpu_device *vdev)
@@ -928,11 +931,14 @@ static void ivpu_hw_mtl_irq_wdt_mss_handler(struct ivpu_device *vdev)
	ivpu_err_ratelimited(vdev, "WDT MSS irq\n");

	ivpu_hw_wdt_disable(vdev);
	ivpu_pm_schedule_recovery(vdev);
}

static void ivpu_hw_mtl_irq_noc_firewall_handler(struct ivpu_device *vdev)
{
	ivpu_err_ratelimited(vdev, "NOC Firewall irq\n");

	ivpu_pm_schedule_recovery(vdev);
}

/* Handler for IRQs from VPU core (irqV) */
@@ -970,6 +976,7 @@ static u32 ivpu_hw_mtl_irqv_handler(struct ivpu_device *vdev, int irq)
static u32 ivpu_hw_mtl_irqb_handler(struct ivpu_device *vdev, int irq)
{
	u32 status = REGB_RD32(MTL_BUTTRESS_INTERRUPT_STAT) & BUTTRESS_IRQ_MASK;
	bool schedule_recovery = false;

	if (status == 0)
		return 0;
@@ -983,6 +990,7 @@ static u32 ivpu_hw_mtl_irqb_handler(struct ivpu_device *vdev, int irq)
	if (REG_TEST_FLD(MTL_BUTTRESS_INTERRUPT_STAT, ATS_ERR, status)) {
		ivpu_err(vdev, "ATS_ERR irq 0x%016llx", REGB_RD64(MTL_BUTTRESS_ATS_ERR_LOG_0));
		REGB_WR32(MTL_BUTTRESS_ATS_ERR_CLEAR, 0x1);
		schedule_recovery = true;
	}

	if (REG_TEST_FLD(MTL_BUTTRESS_INTERRUPT_STAT, UFI_ERR, status)) {
@@ -993,6 +1001,7 @@ static u32 ivpu_hw_mtl_irqb_handler(struct ivpu_device *vdev, int irq)
			 REG_GET_FLD(MTL_BUTTRESS_UFI_ERR_LOG, AXI_ID, ufi_log),
			 REG_GET_FLD(MTL_BUTTRESS_UFI_ERR_LOG, CQ_ID, ufi_log));
		REGB_WR32(MTL_BUTTRESS_UFI_ERR_CLEAR, 0x1);
		schedule_recovery = true;
	}

	/*
@@ -1005,6 +1014,9 @@ static u32 ivpu_hw_mtl_irqb_handler(struct ivpu_device *vdev, int irq)
	/* Re-enable global interrupt */
	REGB_WR32(MTL_BUTTRESS_GLOBAL_INT_MASK, 0x0);

	if (schedule_recovery)
		ivpu_pm_schedule_recovery(vdev);

	return status;
}

Loading