accel/ivpu: Add auto selection logic for job scheduler

Add ivpu_fw_sched_mode_select() function that can select scheduling mode
based on HW and FW versions. This prepares for a switch to HWS on
selected platforms.

Reviewed-by: Karol Wachowski <karol.wachowski@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240930195322.461209-17-jacek.lawrynowicz@linux.intel.com
Signed-off-by: Jacek Lawrynowicz <jacek.lawrynowicz@linux.intel.com>
This commit is contained in:
Jacek Lawrynowicz 2024-09-30 21:53:07 +02:00
parent 707542dd1a
commit 436b67d693
8 changed files with 52 additions and 15 deletions

View File

@ -54,9 +54,9 @@ u8 ivpu_pll_max_ratio = U8_MAX;
module_param_named(pll_max_ratio, ivpu_pll_max_ratio, byte, 0644); module_param_named(pll_max_ratio, ivpu_pll_max_ratio, byte, 0644);
MODULE_PARM_DESC(pll_max_ratio, "Maximum PLL ratio used to set NPU frequency"); MODULE_PARM_DESC(pll_max_ratio, "Maximum PLL ratio used to set NPU frequency");
int ivpu_sched_mode; int ivpu_sched_mode = IVPU_SCHED_MODE_AUTO;
module_param_named(sched_mode, ivpu_sched_mode, int, 0444); module_param_named(sched_mode, ivpu_sched_mode, int, 0444);
MODULE_PARM_DESC(sched_mode, "Scheduler mode: 0 - Default scheduler, 1 - Force HW scheduler"); MODULE_PARM_DESC(sched_mode, "Scheduler mode: -1 - Use default scheduler, 0 - Use OS scheduler, 1 - Use HW scheduler");
bool ivpu_disable_mmu_cont_pages; bool ivpu_disable_mmu_cont_pages;
module_param_named(disable_mmu_cont_pages, ivpu_disable_mmu_cont_pages, bool, 0444); module_param_named(disable_mmu_cont_pages, ivpu_disable_mmu_cont_pages, bool, 0444);
@ -347,7 +347,7 @@ static int ivpu_hw_sched_init(struct ivpu_device *vdev)
{ {
int ret = 0; int ret = 0;
if (vdev->hw->sched_mode == VPU_SCHEDULING_MODE_HW) { if (vdev->fw->sched_mode == VPU_SCHEDULING_MODE_HW) {
ret = ivpu_jsm_hws_setup_priority_bands(vdev); ret = ivpu_jsm_hws_setup_priority_bands(vdev);
if (ret) { if (ret) {
ivpu_err(vdev, "Failed to enable hw scheduler: %d", ret); ivpu_err(vdev, "Failed to enable hw scheduler: %d", ret);

View File

@ -56,6 +56,8 @@
#define IVPU_PLATFORM_FPGA 3 #define IVPU_PLATFORM_FPGA 3
#define IVPU_PLATFORM_INVALID 8 #define IVPU_PLATFORM_INVALID 8
#define IVPU_SCHED_MODE_AUTO -1
#define IVPU_DBG_REG BIT(0) #define IVPU_DBG_REG BIT(0)
#define IVPU_DBG_IRQ BIT(1) #define IVPU_DBG_IRQ BIT(1)
#define IVPU_DBG_MMU BIT(2) #define IVPU_DBG_MMU BIT(2)

View File

@ -134,6 +134,15 @@ static bool is_within_range(u64 addr, size_t size, u64 range_start, size_t range
return true; return true;
} }
static u32
ivpu_fw_sched_mode_select(struct ivpu_device *vdev, const struct vpu_firmware_header *fw_hdr)
{
if (ivpu_sched_mode != IVPU_SCHED_MODE_AUTO)
return ivpu_sched_mode;
return VPU_SCHEDULING_MODE_OS;
}
static int ivpu_fw_parse(struct ivpu_device *vdev) static int ivpu_fw_parse(struct ivpu_device *vdev)
{ {
struct ivpu_fw_info *fw = vdev->fw; struct ivpu_fw_info *fw = vdev->fw;
@ -215,8 +224,10 @@ static int ivpu_fw_parse(struct ivpu_device *vdev)
fw->dvfs_mode = 0; fw->dvfs_mode = 0;
fw->sched_mode = ivpu_fw_sched_mode_select(vdev, fw_hdr);
fw->primary_preempt_buf_size = fw_hdr->preemption_buffer_1_size; fw->primary_preempt_buf_size = fw_hdr->preemption_buffer_1_size;
fw->secondary_preempt_buf_size = fw_hdr->preemption_buffer_2_size; fw->secondary_preempt_buf_size = fw_hdr->preemption_buffer_2_size;
ivpu_info(vdev, "Scheduler mode: %s\n", fw->sched_mode ? "HW" : "OS");
if (fw_hdr->ro_section_start_address && !is_within_range(fw_hdr->ro_section_start_address, if (fw_hdr->ro_section_start_address && !is_within_range(fw_hdr->ro_section_start_address,
fw_hdr->ro_section_size, fw_hdr->ro_section_size,
@ -605,8 +616,8 @@ void ivpu_fw_boot_params_setup(struct ivpu_device *vdev, struct vpu_boot_params
boot_params->punit_telemetry_sram_base = ivpu_hw_telemetry_offset_get(vdev); boot_params->punit_telemetry_sram_base = ivpu_hw_telemetry_offset_get(vdev);
boot_params->punit_telemetry_sram_size = ivpu_hw_telemetry_size_get(vdev); boot_params->punit_telemetry_sram_size = ivpu_hw_telemetry_size_get(vdev);
boot_params->vpu_telemetry_enable = ivpu_hw_telemetry_enable_get(vdev); boot_params->vpu_telemetry_enable = ivpu_hw_telemetry_enable_get(vdev);
boot_params->vpu_scheduling_mode = vdev->hw->sched_mode; boot_params->vpu_scheduling_mode = vdev->fw->sched_mode;
if (vdev->hw->sched_mode == VPU_SCHEDULING_MODE_HW) if (vdev->fw->sched_mode == VPU_SCHEDULING_MODE_HW)
boot_params->vpu_focus_present_timer_ms = IVPU_FOCUS_PRESENT_TIMER_MS; boot_params->vpu_focus_present_timer_ms = IVPU_FOCUS_PRESENT_TIMER_MS;
boot_params->dvfs_mode = vdev->fw->dvfs_mode; boot_params->dvfs_mode = vdev->fw->dvfs_mode;
if (!IVPU_WA(disable_d0i3_msg)) if (!IVPU_WA(disable_d0i3_msg))

View File

@ -6,6 +6,8 @@
#ifndef __IVPU_FW_H__ #ifndef __IVPU_FW_H__
#define __IVPU_FW_H__ #define __IVPU_FW_H__
#include "vpu_jsm_api.h"
#define FW_VERSION_HEADER_SIZE SZ_4K #define FW_VERSION_HEADER_SIZE SZ_4K
#define FW_VERSION_STR_SIZE SZ_256 #define FW_VERSION_STR_SIZE SZ_256
@ -36,6 +38,7 @@ struct ivpu_fw_info {
u32 secondary_preempt_buf_size; u32 secondary_preempt_buf_size;
u64 read_only_addr; u64 read_only_addr;
u32 read_only_size; u32 read_only_size;
u32 sched_mode;
}; };
int ivpu_fw_init(struct ivpu_device *vdev); int ivpu_fw_init(struct ivpu_device *vdev);

View File

@ -46,7 +46,6 @@ struct ivpu_hw_info {
u32 profiling_freq; u32 profiling_freq;
} pll; } pll;
u32 tile_fuse; u32 tile_fuse;
u32 sched_mode;
u32 sku; u32 sku;
u16 config; u16 config;
int dma_bits; int dma_bits;

View File

@ -163,7 +163,6 @@ static int info_init_mtl(struct ivpu_device *vdev)
hw->tile_fuse = BTRS_MTL_TILE_FUSE_ENABLE_BOTH; hw->tile_fuse = BTRS_MTL_TILE_FUSE_ENABLE_BOTH;
hw->sku = BTRS_MTL_TILE_SKU_BOTH; hw->sku = BTRS_MTL_TILE_SKU_BOTH;
hw->config = BTRS_MTL_WP_CONFIG_2_TILE_4_3_RATIO; hw->config = BTRS_MTL_WP_CONFIG_2_TILE_4_3_RATIO;
hw->sched_mode = ivpu_sched_mode;
return 0; return 0;
} }
@ -178,7 +177,6 @@ static int info_init_lnl(struct ivpu_device *vdev)
if (ret) if (ret)
return ret; return ret;
hw->sched_mode = ivpu_sched_mode;
hw->tile_fuse = tile_fuse_config; hw->tile_fuse = tile_fuse_config;
hw->pll.profiling_freq = PLL_PROFILING_FREQ_DEFAULT; hw->pll.profiling_freq = PLL_PROFILING_FREQ_DEFAULT;

View File

@ -37,7 +37,7 @@ static int ivpu_preemption_buffers_create(struct ivpu_device *vdev,
u64 secondary_size = ALIGN(vdev->fw->secondary_preempt_buf_size, PAGE_SIZE); u64 secondary_size = ALIGN(vdev->fw->secondary_preempt_buf_size, PAGE_SIZE);
struct ivpu_addr_range range; struct ivpu_addr_range range;
if (vdev->hw->sched_mode != VPU_SCHEDULING_MODE_HW) if (vdev->fw->sched_mode != VPU_SCHEDULING_MODE_HW)
return 0; return 0;
range.start = vdev->hw->ranges.user.end - (primary_size * IVPU_NUM_CMDQS_PER_CTX); range.start = vdev->hw->ranges.user.end - (primary_size * IVPU_NUM_CMDQS_PER_CTX);
@ -68,7 +68,7 @@ static int ivpu_preemption_buffers_create(struct ivpu_device *vdev,
static void ivpu_preemption_buffers_free(struct ivpu_device *vdev, static void ivpu_preemption_buffers_free(struct ivpu_device *vdev,
struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cmdq) struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cmdq)
{ {
if (vdev->hw->sched_mode != VPU_SCHEDULING_MODE_HW) if (vdev->fw->sched_mode != VPU_SCHEDULING_MODE_HW)
return; return;
drm_WARN_ON(&vdev->drm, !cmdq->primary_preempt_buf); drm_WARN_ON(&vdev->drm, !cmdq->primary_preempt_buf);
@ -149,7 +149,7 @@ static int ivpu_register_db(struct ivpu_file_priv *file_priv, struct ivpu_cmdq *
struct ivpu_device *vdev = file_priv->vdev; struct ivpu_device *vdev = file_priv->vdev;
int ret; int ret;
if (vdev->hw->sched_mode == VPU_SCHEDULING_MODE_HW) if (vdev->fw->sched_mode == VPU_SCHEDULING_MODE_HW)
ret = ivpu_jsm_hws_register_db(vdev, file_priv->ctx.id, cmdq->db_id, cmdq->db_id, ret = ivpu_jsm_hws_register_db(vdev, file_priv->ctx.id, cmdq->db_id, cmdq->db_id,
cmdq->mem->vpu_addr, ivpu_bo_size(cmdq->mem)); cmdq->mem->vpu_addr, ivpu_bo_size(cmdq->mem));
else else
@ -184,7 +184,7 @@ ivpu_cmdq_init(struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cmdq, u16 eng
jobq_header->tail = 0; jobq_header->tail = 0;
wmb(); /* Flush WC buffer for jobq->header */ wmb(); /* Flush WC buffer for jobq->header */
if (vdev->hw->sched_mode == VPU_SCHEDULING_MODE_HW) { if (vdev->fw->sched_mode == VPU_SCHEDULING_MODE_HW) {
ret = ivpu_hws_cmdq_init(file_priv, cmdq, engine, priority); ret = ivpu_hws_cmdq_init(file_priv, cmdq, engine, priority);
if (ret) if (ret)
return ret; return ret;
@ -211,7 +211,7 @@ static int ivpu_cmdq_fini(struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cm
cmdq->db_registered = false; cmdq->db_registered = false;
if (vdev->hw->sched_mode == VPU_SCHEDULING_MODE_HW) { if (vdev->fw->sched_mode == VPU_SCHEDULING_MODE_HW) {
ret = ivpu_jsm_hws_destroy_cmdq(vdev, file_priv->ctx.id, cmdq->db_id); ret = ivpu_jsm_hws_destroy_cmdq(vdev, file_priv->ctx.id, cmdq->db_id);
if (!ret) if (!ret)
ivpu_dbg(vdev, JOB, "Command queue %d destroyed\n", cmdq->db_id); ivpu_dbg(vdev, JOB, "Command queue %d destroyed\n", cmdq->db_id);
@ -335,7 +335,7 @@ void ivpu_context_abort_locked(struct ivpu_file_priv *file_priv)
ivpu_cmdq_fini_all(file_priv); ivpu_cmdq_fini_all(file_priv);
if (vdev->hw->sched_mode == VPU_SCHEDULING_MODE_OS) if (vdev->fw->sched_mode == VPU_SCHEDULING_MODE_OS)
ivpu_jsm_context_release(vdev, file_priv->ctx.id); ivpu_jsm_context_release(vdev, file_priv->ctx.id);
} }
@ -361,7 +361,7 @@ static int ivpu_cmdq_push_job(struct ivpu_cmdq *cmdq, struct ivpu_job *job)
if (unlikely(ivpu_test_mode & IVPU_TEST_MODE_NULL_SUBMISSION)) if (unlikely(ivpu_test_mode & IVPU_TEST_MODE_NULL_SUBMISSION))
entry->flags = VPU_JOB_FLAGS_NULL_SUBMISSION_MASK; entry->flags = VPU_JOB_FLAGS_NULL_SUBMISSION_MASK;
if (vdev->hw->sched_mode == VPU_SCHEDULING_MODE_HW && if (vdev->fw->sched_mode == VPU_SCHEDULING_MODE_HW &&
(unlikely(!(ivpu_test_mode & IVPU_TEST_MODE_PREEMPTION_DISABLE)))) { (unlikely(!(ivpu_test_mode & IVPU_TEST_MODE_PREEMPTION_DISABLE)))) {
entry->primary_preempt_buf_addr = cmdq->primary_preempt_buf->vpu_addr; entry->primary_preempt_buf_addr = cmdq->primary_preempt_buf->vpu_addr;
entry->primary_preempt_buf_size = ivpu_bo_size(cmdq->primary_preempt_buf); entry->primary_preempt_buf_size = ivpu_bo_size(cmdq->primary_preempt_buf);

View File

@ -6,6 +6,8 @@
#include <linux/device.h> #include <linux/device.h>
#include <linux/err.h> #include <linux/err.h>
#include "ivpu_drv.h"
#include "ivpu_fw.h"
#include "ivpu_hw.h" #include "ivpu_hw.h"
#include "ivpu_sysfs.h" #include "ivpu_sysfs.h"
@ -39,8 +41,30 @@ npu_busy_time_us_show(struct device *dev, struct device_attribute *attr, char *b
static DEVICE_ATTR_RO(npu_busy_time_us); static DEVICE_ATTR_RO(npu_busy_time_us);
/**
* DOC: sched_mode
*
* The sched_mode is used to report current NPU scheduling mode.
*
* It returns following strings:
* - "HW" - Hardware Scheduler mode
* - "OS" - Operating System Scheduler mode
*
*/
static ssize_t
sched_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct drm_device *drm = dev_get_drvdata(dev);
struct ivpu_device *vdev = to_ivpu_device(drm);
return sysfs_emit(buf, "%s\n", vdev->fw->sched_mode ? "HW" : "OS");
}
static DEVICE_ATTR_RO(sched_mode);
static struct attribute *ivpu_dev_attrs[] = { static struct attribute *ivpu_dev_attrs[] = {
&dev_attr_npu_busy_time_us.attr, &dev_attr_npu_busy_time_us.attr,
&dev_attr_sched_mode.attr,
NULL, NULL,
}; };