2
0
mirror of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git synced 2025-09-04 20:19:47 +08:00

Short summary of fixes pull:

dma-buf:
 - Correctly decrement refcounter on errors
 
 gem:
 - Fix test for imported buffers
 
 ivpu:
 - Fix debugging
 - Fixes to frequency
 - Support firmware API 3.28.3
 - Flush jobs upon reset
 
 mgag200:
 - Set vblank start to correct values
 
 v3d:
 - Fix Indirect Dispatch
 -----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCgAdFiEEchf7rIzpz2NEoWjlaA3BHVMLeiMFAmgAviQACgkQaA3BHVML
 eiPysQf/fjWwUAWs00ANi9ERtRN4doWNLeDB3vNrIsPB2NEwfc/RwmQvT06Ar7Zb
 /rwudFgGsw7cRK2d7LqjJtfmE/5/qILCTSsRWWgVCtP8bxLmew3WtyurYczvpAc4
 nAAkctNdj9uLl/btc2HimhxGaJzxHv3Wt64GL2ROldqhf8sjs9x0uxMed58UUYsQ
 t/6EqmVyjfigwvIFHj0o5iv7AnFKbWeg3tENyeQMaxOwh+TQyWvAGsJzqhhFLxQV
 JGeU/ARu+ZeKdDkYArDzDUTW0BCetC3lmeg7PMX1Paf4876VAHRaVx5y8xn+LJiA
 xz5BOehz/yJpqvtDd7/J/taw6o4OKw==
 =tU6K
 -----END PGP SIGNATURE-----

Merge tag 'drm-misc-fixes-2025-04-17' of https://gitlab.freedesktop.org/drm/misc/kernel into drm-fixes

Short summary of fixes pull:

dma-buf:
- Correctly decrement refcounter on errors

gem:
- Fix test for imported buffers

ivpu:
- Fix debugging
- Fixes to frequency
- Support firmware API 3.28.3
- Flush jobs upon reset

mgag200:
- Set vblank start to correct values

v3d:
- Fix Indirect Dispatch

Signed-off-by: Dave Airlie <airlied@redhat.com>

From: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://lore.kernel.org/r/20250417084043.GA365738@linux.fritz.box
This commit is contained in:
Dave Airlie 2025-04-18 08:38:26 +10:00
commit 9bca5bcdeb
14 changed files with 226 additions and 132 deletions

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* /*
* Copyright (C) 2020-2024 Intel Corporation * Copyright (C) 2020-2025 Intel Corporation
*/ */
#include <linux/firmware.h> #include <linux/firmware.h>
@ -164,7 +164,7 @@ static int ivpu_get_param_ioctl(struct drm_device *dev, void *data, struct drm_f
args->value = vdev->platform; args->value = vdev->platform;
break; break;
case DRM_IVPU_PARAM_CORE_CLOCK_RATE: case DRM_IVPU_PARAM_CORE_CLOCK_RATE:
args->value = ivpu_hw_ratio_to_freq(vdev, vdev->hw->pll.max_ratio); args->value = ivpu_hw_dpu_max_freq_get(vdev);
break; break;
case DRM_IVPU_PARAM_NUM_CONTEXTS: case DRM_IVPU_PARAM_NUM_CONTEXTS:
args->value = ivpu_get_context_count(vdev); args->value = ivpu_get_context_count(vdev);
@ -421,9 +421,9 @@ void ivpu_prepare_for_reset(struct ivpu_device *vdev)
{ {
ivpu_hw_irq_disable(vdev); ivpu_hw_irq_disable(vdev);
disable_irq(vdev->irq); disable_irq(vdev->irq);
cancel_work_sync(&vdev->irq_ipc_work); flush_work(&vdev->irq_ipc_work);
cancel_work_sync(&vdev->irq_dct_work); flush_work(&vdev->irq_dct_work);
cancel_work_sync(&vdev->context_abort_work); flush_work(&vdev->context_abort_work);
ivpu_ipc_disable(vdev); ivpu_ipc_disable(vdev);
ivpu_mmu_disable(vdev); ivpu_mmu_disable(vdev);
} }

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* /*
* Copyright (C) 2020-2024 Intel Corporation * Copyright (C) 2020-2025 Intel Corporation
*/ */
#include <linux/firmware.h> #include <linux/firmware.h>
@ -233,10 +233,20 @@ 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->sched_mode = ivpu_fw_sched_mode_select(vdev, fw_hdr);
fw->primary_preempt_buf_size = fw_hdr->preemption_buffer_1_size;
fw->secondary_preempt_buf_size = fw_hdr->preemption_buffer_2_size;
ivpu_info(vdev, "Scheduler mode: %s\n", fw->sched_mode ? "HW" : "OS"); ivpu_info(vdev, "Scheduler mode: %s\n", fw->sched_mode ? "HW" : "OS");
if (fw_hdr->preemption_buffer_1_max_size)
fw->primary_preempt_buf_size = fw_hdr->preemption_buffer_1_max_size;
else
fw->primary_preempt_buf_size = fw_hdr->preemption_buffer_1_size;
if (fw_hdr->preemption_buffer_2_max_size)
fw->secondary_preempt_buf_size = fw_hdr->preemption_buffer_2_max_size;
else
fw->secondary_preempt_buf_size = fw_hdr->preemption_buffer_2_size;
ivpu_dbg(vdev, FW_BOOT, "Preemption buffer sizes: primary %u, secondary %u\n",
fw->primary_preempt_buf_size, fw->secondary_preempt_buf_size);
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,
fw_hdr->image_load_address, fw_hdr->image_load_address,
@ -566,7 +576,6 @@ void ivpu_fw_boot_params_setup(struct ivpu_device *vdev, struct vpu_boot_params
boot_params->magic = VPU_BOOT_PARAMS_MAGIC; boot_params->magic = VPU_BOOT_PARAMS_MAGIC;
boot_params->vpu_id = to_pci_dev(vdev->drm.dev)->bus->number; boot_params->vpu_id = to_pci_dev(vdev->drm.dev)->bus->number;
boot_params->frequency = ivpu_hw_pll_freq_get(vdev);
/* /*
* This param is a debug firmware feature. It switches default clock * This param is a debug firmware feature. It switches default clock

View File

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
/* /*
* Copyright (C) 2020-2024 Intel Corporation * Copyright (C) 2020-2025 Intel Corporation
*/ */
#ifndef __IVPU_HW_H__ #ifndef __IVPU_HW_H__
@ -82,9 +82,14 @@ static inline u64 ivpu_hw_range_size(const struct ivpu_addr_range *range)
return range->end - range->start; return range->end - range->start;
} }
static inline u32 ivpu_hw_ratio_to_freq(struct ivpu_device *vdev, u32 ratio) static inline u32 ivpu_hw_dpu_max_freq_get(struct ivpu_device *vdev)
{ {
return ivpu_hw_btrs_ratio_to_freq(vdev, ratio); return ivpu_hw_btrs_dpu_max_freq_get(vdev);
}
static inline u32 ivpu_hw_dpu_freq_get(struct ivpu_device *vdev)
{
return ivpu_hw_btrs_dpu_freq_get(vdev);
} }
static inline void ivpu_hw_irq_clear(struct ivpu_device *vdev) static inline void ivpu_hw_irq_clear(struct ivpu_device *vdev)
@ -92,11 +97,6 @@ static inline void ivpu_hw_irq_clear(struct ivpu_device *vdev)
ivpu_hw_ip_irq_clear(vdev); ivpu_hw_ip_irq_clear(vdev);
} }
static inline u32 ivpu_hw_pll_freq_get(struct ivpu_device *vdev)
{
return ivpu_hw_btrs_pll_freq_get(vdev);
}
static inline u32 ivpu_hw_profiling_freq_get(struct ivpu_device *vdev) static inline u32 ivpu_hw_profiling_freq_get(struct ivpu_device *vdev)
{ {
return vdev->hw->pll.profiling_freq; return vdev->hw->pll.profiling_freq;

View File

@ -1,8 +1,10 @@
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* /*
* Copyright (C) 2020-2024 Intel Corporation * Copyright (C) 2020-2025 Intel Corporation
*/ */
#include <linux/units.h>
#include "ivpu_drv.h" #include "ivpu_drv.h"
#include "ivpu_hw.h" #include "ivpu_hw.h"
#include "ivpu_hw_btrs.h" #include "ivpu_hw_btrs.h"
@ -28,17 +30,13 @@
#define BTRS_LNL_ALL_IRQ_MASK ((u32)-1) #define BTRS_LNL_ALL_IRQ_MASK ((u32)-1)
#define BTRS_MTL_WP_CONFIG_1_TILE_5_3_RATIO WP_CONFIG(MTL_CONFIG_1_TILE, MTL_PLL_RATIO_5_3)
#define BTRS_MTL_WP_CONFIG_1_TILE_4_3_RATIO WP_CONFIG(MTL_CONFIG_1_TILE, MTL_PLL_RATIO_4_3)
#define BTRS_MTL_WP_CONFIG_2_TILE_5_3_RATIO WP_CONFIG(MTL_CONFIG_2_TILE, MTL_PLL_RATIO_5_3)
#define BTRS_MTL_WP_CONFIG_2_TILE_4_3_RATIO WP_CONFIG(MTL_CONFIG_2_TILE, MTL_PLL_RATIO_4_3)
#define BTRS_MTL_WP_CONFIG_0_TILE_PLL_OFF WP_CONFIG(0, 0)
#define PLL_CDYN_DEFAULT 0x80 #define PLL_CDYN_DEFAULT 0x80
#define PLL_EPP_DEFAULT 0x80 #define PLL_EPP_DEFAULT 0x80
#define PLL_CONFIG_DEFAULT 0x0 #define PLL_CONFIG_DEFAULT 0x0
#define PLL_SIMULATION_FREQ 10000000 #define PLL_REF_CLK_FREQ 50000000ull
#define PLL_REF_CLK_FREQ 50000000 #define PLL_RATIO_TO_FREQ(x) ((x) * PLL_REF_CLK_FREQ)
#define PLL_TIMEOUT_US (1500 * USEC_PER_MSEC) #define PLL_TIMEOUT_US (1500 * USEC_PER_MSEC)
#define IDLE_TIMEOUT_US (5 * USEC_PER_MSEC) #define IDLE_TIMEOUT_US (5 * USEC_PER_MSEC)
#define TIMEOUT_US (150 * USEC_PER_MSEC) #define TIMEOUT_US (150 * USEC_PER_MSEC)
@ -62,6 +60,8 @@
#define DCT_ENABLE 0x1 #define DCT_ENABLE 0x1
#define DCT_DISABLE 0x0 #define DCT_DISABLE 0x0
static u32 pll_ratio_to_dpu_freq(struct ivpu_device *vdev, u32 ratio);
int ivpu_hw_btrs_irqs_clear_with_0_mtl(struct ivpu_device *vdev) int ivpu_hw_btrs_irqs_clear_with_0_mtl(struct ivpu_device *vdev)
{ {
REGB_WR32(VPU_HW_BTRS_MTL_INTERRUPT_STAT, BTRS_MTL_ALL_IRQ_MASK); REGB_WR32(VPU_HW_BTRS_MTL_INTERRUPT_STAT, BTRS_MTL_ALL_IRQ_MASK);
@ -156,7 +156,7 @@ 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 = WP_CONFIG(MTL_CONFIG_2_TILE, MTL_PLL_RATIO_4_3);
return 0; return 0;
} }
@ -334,8 +334,8 @@ int ivpu_hw_btrs_wp_drive(struct ivpu_device *vdev, bool enable)
prepare_wp_request(vdev, &wp, enable); prepare_wp_request(vdev, &wp, enable);
ivpu_dbg(vdev, PM, "PLL workpoint request: %u Hz, config: 0x%x, epp: 0x%x, cdyn: 0x%x\n", ivpu_dbg(vdev, PM, "PLL workpoint request: %lu MHz, config: 0x%x, epp: 0x%x, cdyn: 0x%x\n",
PLL_RATIO_TO_FREQ(wp.target), wp.cfg, wp.epp, wp.cdyn); pll_ratio_to_dpu_freq(vdev, wp.target) / HZ_PER_MHZ, wp.cfg, wp.epp, wp.cdyn);
ret = wp_request_send(vdev, &wp); ret = wp_request_send(vdev, &wp);
if (ret) { if (ret) {
@ -573,6 +573,47 @@ int ivpu_hw_btrs_wait_for_idle(struct ivpu_device *vdev)
return REGB_POLL_FLD(VPU_HW_BTRS_LNL_VPU_STATUS, IDLE, 0x1, IDLE_TIMEOUT_US); return REGB_POLL_FLD(VPU_HW_BTRS_LNL_VPU_STATUS, IDLE, 0x1, IDLE_TIMEOUT_US);
} }
static u32 pll_config_get_mtl(struct ivpu_device *vdev)
{
return REGB_RD32(VPU_HW_BTRS_MTL_CURRENT_PLL);
}
static u32 pll_config_get_lnl(struct ivpu_device *vdev)
{
return REGB_RD32(VPU_HW_BTRS_LNL_PLL_FREQ);
}
static u32 pll_ratio_to_dpu_freq_mtl(u16 ratio)
{
return (PLL_RATIO_TO_FREQ(ratio) * 2) / 3;
}
static u32 pll_ratio_to_dpu_freq_lnl(u16 ratio)
{
return PLL_RATIO_TO_FREQ(ratio) / 2;
}
static u32 pll_ratio_to_dpu_freq(struct ivpu_device *vdev, u32 ratio)
{
if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
return pll_ratio_to_dpu_freq_mtl(ratio);
else
return pll_ratio_to_dpu_freq_lnl(ratio);
}
u32 ivpu_hw_btrs_dpu_max_freq_get(struct ivpu_device *vdev)
{
return pll_ratio_to_dpu_freq(vdev, vdev->hw->pll.max_ratio);
}
u32 ivpu_hw_btrs_dpu_freq_get(struct ivpu_device *vdev)
{
if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
return pll_ratio_to_dpu_freq_mtl(pll_config_get_mtl(vdev));
else
return pll_ratio_to_dpu_freq_lnl(pll_config_get_lnl(vdev));
}
/* Handler for IRQs from Buttress core (irqB) */ /* Handler for IRQs from Buttress core (irqB) */
bool ivpu_hw_btrs_irq_handler_mtl(struct ivpu_device *vdev, int irq) bool ivpu_hw_btrs_irq_handler_mtl(struct ivpu_device *vdev, int irq)
{ {
@ -582,9 +623,12 @@ bool ivpu_hw_btrs_irq_handler_mtl(struct ivpu_device *vdev, int irq)
if (!status) if (!status)
return false; return false;
if (REG_TEST_FLD(VPU_HW_BTRS_MTL_INTERRUPT_STAT, FREQ_CHANGE, status)) if (REG_TEST_FLD(VPU_HW_BTRS_MTL_INTERRUPT_STAT, FREQ_CHANGE, status)) {
ivpu_dbg(vdev, IRQ, "FREQ_CHANGE irq: %08x", u32 pll = pll_config_get_mtl(vdev);
REGB_RD32(VPU_HW_BTRS_MTL_CURRENT_PLL));
ivpu_dbg(vdev, IRQ, "FREQ_CHANGE irq, wp %08x, %lu MHz",
pll, pll_ratio_to_dpu_freq_mtl(pll) / HZ_PER_MHZ);
}
if (REG_TEST_FLD(VPU_HW_BTRS_MTL_INTERRUPT_STAT, ATS_ERR, status)) { if (REG_TEST_FLD(VPU_HW_BTRS_MTL_INTERRUPT_STAT, ATS_ERR, status)) {
ivpu_err(vdev, "ATS_ERR irq 0x%016llx", REGB_RD64(VPU_HW_BTRS_MTL_ATS_ERR_LOG_0)); ivpu_err(vdev, "ATS_ERR irq 0x%016llx", REGB_RD64(VPU_HW_BTRS_MTL_ATS_ERR_LOG_0));
@ -633,8 +677,12 @@ bool ivpu_hw_btrs_irq_handler_lnl(struct ivpu_device *vdev, int irq)
queue_work(system_wq, &vdev->irq_dct_work); queue_work(system_wq, &vdev->irq_dct_work);
} }
if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, FREQ_CHANGE, status)) if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, FREQ_CHANGE, status)) {
ivpu_dbg(vdev, IRQ, "FREQ_CHANGE irq: %08x", REGB_RD32(VPU_HW_BTRS_LNL_PLL_FREQ)); u32 pll = pll_config_get_lnl(vdev);
ivpu_dbg(vdev, IRQ, "FREQ_CHANGE irq, wp %08x, %lu MHz",
pll, pll_ratio_to_dpu_freq_lnl(pll) / HZ_PER_MHZ);
}
if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, ATS_ERR, status)) { if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, ATS_ERR, status)) {
ivpu_err(vdev, "ATS_ERR LOG1 0x%08x ATS_ERR_LOG2 0x%08x\n", ivpu_err(vdev, "ATS_ERR LOG1 0x%08x ATS_ERR_LOG2 0x%08x\n",
@ -717,60 +765,6 @@ void ivpu_hw_btrs_dct_set_status(struct ivpu_device *vdev, bool enable, u32 acti
REGB_WR32(VPU_HW_BTRS_LNL_PCODE_MAILBOX_STATUS, val); REGB_WR32(VPU_HW_BTRS_LNL_PCODE_MAILBOX_STATUS, val);
} }
static u32 pll_ratio_to_freq_mtl(u32 ratio, u32 config)
{
u32 pll_clock = PLL_REF_CLK_FREQ * ratio;
u32 cpu_clock;
if ((config & 0xff) == MTL_PLL_RATIO_4_3)
cpu_clock = pll_clock * 2 / 4;
else
cpu_clock = pll_clock * 2 / 5;
return cpu_clock;
}
u32 ivpu_hw_btrs_ratio_to_freq(struct ivpu_device *vdev, u32 ratio)
{
struct ivpu_hw_info *hw = vdev->hw;
if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
return pll_ratio_to_freq_mtl(ratio, hw->config);
else
return PLL_RATIO_TO_FREQ(ratio);
}
static u32 pll_freq_get_mtl(struct ivpu_device *vdev)
{
u32 pll_curr_ratio;
pll_curr_ratio = REGB_RD32(VPU_HW_BTRS_MTL_CURRENT_PLL);
pll_curr_ratio &= VPU_HW_BTRS_MTL_CURRENT_PLL_RATIO_MASK;
if (!ivpu_is_silicon(vdev))
return PLL_SIMULATION_FREQ;
return pll_ratio_to_freq_mtl(pll_curr_ratio, vdev->hw->config);
}
static u32 pll_freq_get_lnl(struct ivpu_device *vdev)
{
u32 pll_curr_ratio;
pll_curr_ratio = REGB_RD32(VPU_HW_BTRS_LNL_PLL_FREQ);
pll_curr_ratio &= VPU_HW_BTRS_LNL_PLL_FREQ_RATIO_MASK;
return PLL_RATIO_TO_FREQ(pll_curr_ratio);
}
u32 ivpu_hw_btrs_pll_freq_get(struct ivpu_device *vdev)
{
if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
return pll_freq_get_mtl(vdev);
else
return pll_freq_get_lnl(vdev);
}
u32 ivpu_hw_btrs_telemetry_offset_get(struct ivpu_device *vdev) u32 ivpu_hw_btrs_telemetry_offset_get(struct ivpu_device *vdev)
{ {
if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL) if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)

View File

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
/* /*
* Copyright (C) 2020-2024 Intel Corporation * Copyright (C) 2020-2025 Intel Corporation
*/ */
#ifndef __IVPU_HW_BTRS_H__ #ifndef __IVPU_HW_BTRS_H__
@ -13,7 +13,6 @@
#define PLL_PROFILING_FREQ_DEFAULT 38400000 #define PLL_PROFILING_FREQ_DEFAULT 38400000
#define PLL_PROFILING_FREQ_HIGH 400000000 #define PLL_PROFILING_FREQ_HIGH 400000000
#define PLL_RATIO_TO_FREQ(x) ((x) * PLL_REF_CLK_FREQ)
#define DCT_DEFAULT_ACTIVE_PERCENT 15u #define DCT_DEFAULT_ACTIVE_PERCENT 15u
#define DCT_PERIOD_US 35300u #define DCT_PERIOD_US 35300u
@ -32,12 +31,12 @@ int ivpu_hw_btrs_ip_reset(struct ivpu_device *vdev);
void ivpu_hw_btrs_profiling_freq_reg_set_lnl(struct ivpu_device *vdev); void ivpu_hw_btrs_profiling_freq_reg_set_lnl(struct ivpu_device *vdev);
void ivpu_hw_btrs_ats_print_lnl(struct ivpu_device *vdev); void ivpu_hw_btrs_ats_print_lnl(struct ivpu_device *vdev);
void ivpu_hw_btrs_clock_relinquish_disable_lnl(struct ivpu_device *vdev); void ivpu_hw_btrs_clock_relinquish_disable_lnl(struct ivpu_device *vdev);
u32 ivpu_hw_btrs_dpu_max_freq_get(struct ivpu_device *vdev);
u32 ivpu_hw_btrs_dpu_freq_get(struct ivpu_device *vdev);
bool ivpu_hw_btrs_irq_handler_mtl(struct ivpu_device *vdev, int irq); bool ivpu_hw_btrs_irq_handler_mtl(struct ivpu_device *vdev, int irq);
bool ivpu_hw_btrs_irq_handler_lnl(struct ivpu_device *vdev, int irq); bool ivpu_hw_btrs_irq_handler_lnl(struct ivpu_device *vdev, int irq);
int ivpu_hw_btrs_dct_get_request(struct ivpu_device *vdev, bool *enable); int ivpu_hw_btrs_dct_get_request(struct ivpu_device *vdev, bool *enable);
void ivpu_hw_btrs_dct_set_status(struct ivpu_device *vdev, bool enable, u32 dct_percent); void ivpu_hw_btrs_dct_set_status(struct ivpu_device *vdev, bool enable, u32 dct_percent);
u32 ivpu_hw_btrs_pll_freq_get(struct ivpu_device *vdev);
u32 ivpu_hw_btrs_ratio_to_freq(struct ivpu_device *vdev, u32 ratio);
u32 ivpu_hw_btrs_telemetry_offset_get(struct ivpu_device *vdev); u32 ivpu_hw_btrs_telemetry_offset_get(struct ivpu_device *vdev);
u32 ivpu_hw_btrs_telemetry_size_get(struct ivpu_device *vdev); u32 ivpu_hw_btrs_telemetry_size_get(struct ivpu_device *vdev);
u32 ivpu_hw_btrs_telemetry_enable_get(struct ivpu_device *vdev); u32 ivpu_hw_btrs_telemetry_enable_get(struct ivpu_device *vdev);

View File

@ -470,8 +470,8 @@ static void ivpu_job_destroy(struct ivpu_job *job)
struct ivpu_device *vdev = job->vdev; struct ivpu_device *vdev = job->vdev;
u32 i; u32 i;
ivpu_dbg(vdev, JOB, "Job destroyed: id %3u ctx %2d engine %d", ivpu_dbg(vdev, JOB, "Job destroyed: id %3u ctx %2d cmdq_id %u engine %d",
job->job_id, job->file_priv->ctx.id, job->engine_idx); job->job_id, job->file_priv->ctx.id, job->cmdq_id, job->engine_idx);
for (i = 0; i < job->bo_count; i++) for (i = 0; i < job->bo_count; i++)
if (job->bos[i]) if (job->bos[i])
@ -564,8 +564,8 @@ static int ivpu_job_signal_and_destroy(struct ivpu_device *vdev, u32 job_id, u32
dma_fence_signal(job->done_fence); dma_fence_signal(job->done_fence);
trace_job("done", job); trace_job("done", job);
ivpu_dbg(vdev, JOB, "Job complete: id %3u ctx %2d engine %d status 0x%x\n", ivpu_dbg(vdev, JOB, "Job complete: id %3u ctx %2d cmdq_id %u engine %d status 0x%x\n",
job->job_id, job->file_priv->ctx.id, job->engine_idx, job_status); job->job_id, job->file_priv->ctx.id, job->cmdq_id, job->engine_idx, job_status);
ivpu_job_destroy(job); ivpu_job_destroy(job);
ivpu_stop_job_timeout_detection(vdev); ivpu_stop_job_timeout_detection(vdev);
@ -664,8 +664,8 @@ static int ivpu_job_submit(struct ivpu_job *job, u8 priority, u32 cmdq_id)
} }
trace_job("submit", job); trace_job("submit", job);
ivpu_dbg(vdev, JOB, "Job submitted: id %3u ctx %2d engine %d prio %d addr 0x%llx next %d\n", ivpu_dbg(vdev, JOB, "Job submitted: id %3u ctx %2d cmdq_id %u engine %d prio %d addr 0x%llx next %d\n",
job->job_id, file_priv->ctx.id, job->engine_idx, cmdq->priority, job->job_id, file_priv->ctx.id, cmdq->id, job->engine_idx, cmdq->priority,
job->cmd_buf_vpu_addr, cmdq->jobq->header.tail); job->cmd_buf_vpu_addr, cmdq->jobq->header.tail);
mutex_unlock(&file_priv->lock); mutex_unlock(&file_priv->lock);
@ -777,7 +777,8 @@ static int ivpu_submit(struct drm_file *file, struct ivpu_file_priv *file_priv,
goto err_free_handles; goto err_free_handles;
} }
ivpu_dbg(vdev, JOB, "Submit ioctl: ctx %u buf_count %u\n", file_priv->ctx.id, buffer_count); ivpu_dbg(vdev, JOB, "Submit ioctl: ctx %u cmdq_id %u buf_count %u\n",
file_priv->ctx.id, cmdq_id, buffer_count);
job = ivpu_job_create(file_priv, engine, buffer_count); job = ivpu_job_create(file_priv, engine, buffer_count);
if (!job) { if (!job) {

View File

@ -1,10 +1,12 @@
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* /*
* Copyright (C) 2024 Intel Corporation * Copyright (C) 2024-2025 Intel Corporation
*/ */
#include <linux/device.h> #include <linux/device.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/pm_runtime.h>
#include <linux/units.h>
#include "ivpu_drv.h" #include "ivpu_drv.h"
#include "ivpu_gem.h" #include "ivpu_gem.h"
@ -90,10 +92,55 @@ sched_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
static DEVICE_ATTR_RO(sched_mode); static DEVICE_ATTR_RO(sched_mode);
/**
* DOC: npu_max_frequency
*
* The npu_max_frequency shows maximum frequency in MHz of the NPU's data
* processing unit
*/
static ssize_t
npu_max_frequency_mhz_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);
u32 freq = ivpu_hw_dpu_max_freq_get(vdev);
return sysfs_emit(buf, "%lu\n", freq / HZ_PER_MHZ);
}
static DEVICE_ATTR_RO(npu_max_frequency_mhz);
/**
* DOC: npu_current_frequency_mhz
*
* The npu_current_frequency_mhz shows current frequency in MHz of the NPU's
* data processing unit
*/
static ssize_t
npu_current_frequency_mhz_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);
u32 freq = 0;
/* Read frequency only if device is active, otherwise frequency is 0 */
if (pm_runtime_get_if_active(vdev->drm.dev) > 0) {
freq = ivpu_hw_dpu_freq_get(vdev);
pm_runtime_put_autosuspend(vdev->drm.dev);
}
return sysfs_emit(buf, "%lu\n", freq / HZ_PER_MHZ);
}
static DEVICE_ATTR_RO(npu_current_frequency_mhz);
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_npu_memory_utilization.attr, &dev_attr_npu_memory_utilization.attr,
&dev_attr_sched_mode.attr, &dev_attr_sched_mode.attr,
&dev_attr_npu_max_frequency_mhz.attr,
&dev_attr_npu_current_frequency_mhz.attr,
NULL, NULL,
}; };

View File

@ -26,7 +26,7 @@
* Minor version changes when API backward compatibility is preserved. * Minor version changes when API backward compatibility is preserved.
* Resets to 0 if Major version is incremented. * Resets to 0 if Major version is incremented.
*/ */
#define VPU_BOOT_API_VER_MINOR 26 #define VPU_BOOT_API_VER_MINOR 28
/* /*
* API header changed (field names, documentation, formatting) but API itself has not been changed * API header changed (field names, documentation, formatting) but API itself has not been changed
@ -76,8 +76,15 @@ struct vpu_firmware_header {
* submission queue size and device capabilities. * submission queue size and device capabilities.
*/ */
u32 preemption_buffer_2_size; u32 preemption_buffer_2_size;
/*
* Maximum preemption buffer size that the FW can use: no need for the host
* driver to allocate more space than that specified by these fields.
* A value of 0 means no declared limit.
*/
u32 preemption_buffer_1_max_size;
u32 preemption_buffer_2_max_size;
/* Space reserved for future preemption-related fields. */ /* Space reserved for future preemption-related fields. */
u32 preemption_reserved[6]; u32 preemption_reserved[4];
/* FW image read only section start address, 4KB aligned */ /* FW image read only section start address, 4KB aligned */
u64 ro_section_start_address; u64 ro_section_start_address;
/* FW image read only section size, 4KB aligned */ /* FW image read only section size, 4KB aligned */
@ -134,7 +141,7 @@ enum vpu_trace_destination {
/* /*
* Processor bit shifts (for loggable HW components). * Processor bit shifts (for loggable HW components).
*/ */
#define VPU_TRACE_PROC_BIT_ARM 0 #define VPU_TRACE_PROC_BIT_RESERVED 0
#define VPU_TRACE_PROC_BIT_LRT 1 #define VPU_TRACE_PROC_BIT_LRT 1
#define VPU_TRACE_PROC_BIT_LNN 2 #define VPU_TRACE_PROC_BIT_LNN 2
#define VPU_TRACE_PROC_BIT_SHV_0 3 #define VPU_TRACE_PROC_BIT_SHV_0 3

View File

@ -22,7 +22,7 @@
/* /*
* Minor version changes when API backward compatibility is preserved. * Minor version changes when API backward compatibility is preserved.
*/ */
#define VPU_JSM_API_VER_MINOR 25 #define VPU_JSM_API_VER_MINOR 29
/* /*
* API header changed (field names, documentation, formatting) but API itself has not been changed * API header changed (field names, documentation, formatting) but API itself has not been changed
@ -53,8 +53,7 @@
* Engine indexes. * Engine indexes.
*/ */
#define VPU_ENGINE_COMPUTE 0 #define VPU_ENGINE_COMPUTE 0
#define VPU_ENGINE_COPY 1 #define VPU_ENGINE_NB 1
#define VPU_ENGINE_NB 2
/* /*
* VPU status values. * VPU status values.
@ -126,11 +125,13 @@ enum {
* When set, indicates that job queue uses native fences (as inline commands * When set, indicates that job queue uses native fences (as inline commands
* in job queue). Such queues may also use legacy fences (as commands in batch buffers). * in job queue). Such queues may also use legacy fences (as commands in batch buffers).
* When cleared, indicates the job queue only uses legacy fences. * When cleared, indicates the job queue only uses legacy fences.
* NOTE: For queues using native fences, VPU expects that all jobs in the queue * NOTES:
* are immediately followed by an inline command object. This object is expected * 1. For queues using native fences, VPU expects that all jobs in the queue
* to be a fence signal command in most cases, but can also be a NOP in case the host * are immediately followed by an inline command object. This object is expected
* does not need per-job fence signalling. Other inline commands objects can be * to be a fence signal command in most cases, but can also be a NOP in case the host
* inserted between "job and inline command" pairs. * does not need per-job fence signalling. Other inline commands objects can be
* inserted between "job and inline command" pairs.
* 2. Native fence queues are only supported on VPU 40xx onwards.
*/ */
VPU_JOB_QUEUE_FLAGS_USE_NATIVE_FENCE_MASK = (1 << 1U), VPU_JOB_QUEUE_FLAGS_USE_NATIVE_FENCE_MASK = (1 << 1U),
@ -275,6 +276,8 @@ struct vpu_inline_cmd {
u64 value; u64 value;
/* User VA of the log buffer in which to add log entry on completion. */ /* User VA of the log buffer in which to add log entry on completion. */
u64 log_buffer_va; u64 log_buffer_va;
/* NPU private data. */
u64 npu_private_data;
} fence; } fence;
/* Other commands do not have a payload. */ /* Other commands do not have a payload. */
/* Payload definition for future inline commands can be inserted here. */ /* Payload definition for future inline commands can be inserted here. */
@ -791,12 +794,22 @@ struct vpu_jsm_metric_streamer_update {
/** Metric group mask that identifies metric streamer instance. */ /** Metric group mask that identifies metric streamer instance. */
u64 metric_group_mask; u64 metric_group_mask;
/** /**
* Address and size of the buffer where the VPU will write metric data. If * Address and size of the buffer where the VPU will write metric data.
* the buffer address is 0 or same as the currently used buffer the VPU will * This member dictates how the update operation should perform:
* continue writing metric data to the current buffer. In this case the * 1. client needs information about the number of collected samples and the
* buffer size is ignored and the size of the current buffer is unchanged. * amount of data written to the current buffer
* If the address is non-zero and differs from the current buffer address the * 2. client wants to switch to a new buffer
* VPU will immediately switch data collection to the new buffer. *
* Case 1. is identified by the buffer address being 0 or the same as the
* currently used buffer address. In this case the buffer size is ignored and
* the size of the current buffer is unchanged. The VPU will return an update
* in the vpu_jsm_metric_streamer_done structure. The internal writing position
* into the buffer is not changed.
*
* Case 2. is identified by the address being non-zero and differs from the
* current buffer address. The VPU will immediately switch data collection to
* the new buffer. Then the VPU will return an update in the
* vpu_jsm_metric_streamer_done structure.
*/ */
u64 buffer_addr; u64 buffer_addr;
u64 buffer_size; u64 buffer_size;
@ -934,6 +947,7 @@ struct vpu_ipc_msg_payload_hws_priority_band_setup {
/* /*
* Default quantum in 100ns units for scheduling across processes * Default quantum in 100ns units for scheduling across processes
* within a priority band * within a priority band
* Minimum value supported by NPU is 1ms (10000 in 100ns units).
*/ */
u32 process_quantum[VPU_HWS_NUM_PRIORITY_BANDS]; u32 process_quantum[VPU_HWS_NUM_PRIORITY_BANDS];
/* /*
@ -946,8 +960,10 @@ struct vpu_ipc_msg_payload_hws_priority_band_setup {
* in situations when it's starved by the focus band. * in situations when it's starved by the focus band.
*/ */
u32 normal_band_percentage; u32 normal_band_percentage;
/* Reserved */ /*
u32 reserved_0; * TDR timeout value in milliseconds. Default value of 0 meaning no timeout.
*/
u32 tdr_timeout;
}; };
/* /*
@ -1024,7 +1040,10 @@ struct vpu_ipc_msg_payload_hws_set_context_sched_properties {
s32 in_process_priority; s32 in_process_priority;
/* Zero padding / Reserved */ /* Zero padding / Reserved */
u32 reserved_1; u32 reserved_1;
/* Context quantum relative to other contexts of same priority in the same process */ /*
* Context quantum relative to other contexts of same priority in the same process
* Minimum value supported by NPU is 1ms (10000 in 100ns units).
*/
u64 context_quantum; u64 context_quantum;
/* Grace period when preempting context of the same priority within the same process */ /* Grace period when preempting context of the same priority within the same process */
u64 grace_period_same_priority; u64 grace_period_same_priority;

View File

@ -438,15 +438,17 @@ static int sw_sync_ioctl_get_deadline(struct sync_timeline *obj, unsigned long a
return -EINVAL; return -EINVAL;
pt = dma_fence_to_sync_pt(fence); pt = dma_fence_to_sync_pt(fence);
if (!pt) if (!pt) {
return -EINVAL; ret = -EINVAL;
goto put_fence;
}
spin_lock_irqsave(fence->lock, flags); spin_lock_irqsave(fence->lock, flags);
if (test_bit(SW_SYNC_HAS_DEADLINE_BIT, &fence->flags)) { if (!test_bit(SW_SYNC_HAS_DEADLINE_BIT, &fence->flags)) {
data.deadline_ns = ktime_to_ns(pt->deadline);
} else {
ret = -ENOENT; ret = -ENOENT;
goto unlock;
} }
data.deadline_ns = ktime_to_ns(pt->deadline);
spin_unlock_irqrestore(fence->lock, flags); spin_unlock_irqrestore(fence->lock, flags);
dma_fence_put(fence); dma_fence_put(fence);
@ -458,6 +460,13 @@ static int sw_sync_ioctl_get_deadline(struct sync_timeline *obj, unsigned long a
return -EFAULT; return -EFAULT;
return 0; return 0;
unlock:
spin_unlock_irqrestore(fence->lock, flags);
put_fence:
dma_fence_put(fence);
return ret;
} }
static long sw_sync_ioctl(struct file *file, unsigned int cmd, static long sw_sync_ioctl(struct file *file, unsigned int cmd,

View File

@ -223,7 +223,7 @@ void mgag200_set_mode_regs(struct mga_device *mdev, const struct drm_display_mod
vsyncstr = mode->crtc_vsync_start - 1; vsyncstr = mode->crtc_vsync_start - 1;
vsyncend = mode->crtc_vsync_end - 1; vsyncend = mode->crtc_vsync_end - 1;
vtotal = mode->crtc_vtotal - 2; vtotal = mode->crtc_vtotal - 2;
vblkstr = mode->crtc_vblank_start; vblkstr = mode->crtc_vblank_start - 1;
vblkend = vtotal + 1; vblkend = vtotal + 1;
linecomp = vdispend; linecomp = vdispend;

View File

@ -428,7 +428,8 @@ v3d_rewrite_csd_job_wg_counts_from_indirect(struct v3d_cpu_job *job)
struct v3d_bo *bo = to_v3d_bo(job->base.bo[0]); struct v3d_bo *bo = to_v3d_bo(job->base.bo[0]);
struct v3d_bo *indirect = to_v3d_bo(indirect_csd->indirect); struct v3d_bo *indirect = to_v3d_bo(indirect_csd->indirect);
struct drm_v3d_submit_csd *args = &indirect_csd->job->args; struct drm_v3d_submit_csd *args = &indirect_csd->job->args;
u32 *wg_counts; struct v3d_dev *v3d = job->base.v3d;
u32 num_batches, *wg_counts;
v3d_get_bo_vaddr(bo); v3d_get_bo_vaddr(bo);
v3d_get_bo_vaddr(indirect); v3d_get_bo_vaddr(indirect);
@ -441,8 +442,17 @@ v3d_rewrite_csd_job_wg_counts_from_indirect(struct v3d_cpu_job *job)
args->cfg[0] = wg_counts[0] << V3D_CSD_CFG012_WG_COUNT_SHIFT; args->cfg[0] = wg_counts[0] << V3D_CSD_CFG012_WG_COUNT_SHIFT;
args->cfg[1] = wg_counts[1] << V3D_CSD_CFG012_WG_COUNT_SHIFT; args->cfg[1] = wg_counts[1] << V3D_CSD_CFG012_WG_COUNT_SHIFT;
args->cfg[2] = wg_counts[2] << V3D_CSD_CFG012_WG_COUNT_SHIFT; args->cfg[2] = wg_counts[2] << V3D_CSD_CFG012_WG_COUNT_SHIFT;
args->cfg[4] = DIV_ROUND_UP(indirect_csd->wg_size, 16) *
(wg_counts[0] * wg_counts[1] * wg_counts[2]) - 1; num_batches = DIV_ROUND_UP(indirect_csd->wg_size, 16) *
(wg_counts[0] * wg_counts[1] * wg_counts[2]);
/* V3D 7.1.6 and later don't subtract 1 from the number of batches */
if (v3d->ver < 71 || (v3d->ver == 71 && v3d->rev < 6))
args->cfg[4] = num_batches - 1;
else
args->cfg[4] = num_batches;
WARN_ON(args->cfg[4] == ~0);
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
/* 0xffffffff indicates that the uniform rewrite is not needed */ /* 0xffffffff indicates that the uniform rewrite is not needed */

View File

@ -585,8 +585,7 @@ static inline bool drm_gem_object_is_shared_for_memory_stats(struct drm_gem_obje
*/ */
static inline bool drm_gem_is_imported(const struct drm_gem_object *obj) static inline bool drm_gem_is_imported(const struct drm_gem_object *obj)
{ {
/* The dma-buf's priv field points to the original GEM object. */ return !!obj->import_attach;
return obj->dma_buf && (obj->dma_buf->priv != obj);
} }
#ifdef CONFIG_LOCKDEP #ifdef CONFIG_LOCKDEP

View File

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ /* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
/* /*
* Copyright (C) 2020-2024 Intel Corporation * Copyright (C) 2020-2025 Intel Corporation
*/ */
#ifndef __UAPI_IVPU_DRM_H__ #ifndef __UAPI_IVPU_DRM_H__
@ -147,7 +147,7 @@ struct drm_ivpu_param {
* platform type when executing on a simulator or emulator (read-only) * platform type when executing on a simulator or emulator (read-only)
* *
* %DRM_IVPU_PARAM_CORE_CLOCK_RATE: * %DRM_IVPU_PARAM_CORE_CLOCK_RATE:
* Current PLL frequency (read-only) * Maximum frequency of the NPU data processing unit clock (read-only)
* *
* %DRM_IVPU_PARAM_NUM_CONTEXTS: * %DRM_IVPU_PARAM_NUM_CONTEXTS:
* Maximum number of simultaneously existing contexts (read-only) * Maximum number of simultaneously existing contexts (read-only)