mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-02-19 20:40:50 -05:00
Merge tag 'drm-fixes-2024-11-09' of https://gitlab.freedesktop.org/drm/kernel
Pull drm fixes from Dave Airlie:
"Weekly fixes, usual leaders in amdgpu and xe, then a panel quirk, and
some fixes to imagination and panthor drivers. Seems around the usual
level for this time and don't know of any big problems.
amdgpu:
- Brightness fix
- DC vbios parsing fix
- ACPI fix
- SMU 14.x fix
- Power workload profile fix
- GC partitioning fix
- Debugfs fixes
imagination:
- Track PVR context per file
- Break ref-counting cycle
panel-orientation-quirks:
- Fix matching Lenovo Yoga Tab 3 X90F
panthor:
- Lock VM array
- Be strict about I/O mapping flags
xe:
- Fix ccs_mode setting for Xe2 and later
- Synchronize ccs_mode setting with client creation
- Apply scheduling WA for LNL in additional places as needed
- Fix leak and lock handling in error paths of xe_exec ioctl
- Fix GGTT allocation leak leading to eventual crash in SR-IOV
- Move run_ticks update out of job handling to avoid synchronization
with reader"
* tag 'drm-fixes-2024-11-09' of https://gitlab.freedesktop.org/drm/kernel: (23 commits)
drm/panthor: Be stricter about IO mapping flags
drm/panthor: Lock XArray when getting entries for the VM
drm: panel-orientation-quirks: Make Lenovo Yoga Tab 3 X90F DMI match less strict
drm/xe: Stop accumulating LRC timestamp on job_free
drm/xe/pf: Fix potential GGTT allocation leak
drm/xe: Drop VM dma-resv lock on xe_sync_in_fence_get failure in exec IOCTL
drm/xe: Fix possible exec queue leak in exec IOCTL
drm/amdgpu: add missing size check in amdgpu_debugfs_gprwave_read()
drm/amdgpu: Adjust debugfs eviction and IB access permissions
drm/amdgpu: Adjust debugfs register access permissions
drm/amdgpu: Fix DPX valid mode check on GC 9.4.3
drm/amd/pm: correct the workload setting
drm/amd/pm: always pick the pptable from IFWI
drm/amdgpu: prevent NULL pointer dereference if ATIF is not supported
drm/amd/display: parse umc_info or vram_info based on ASIC
drm/amd/display: Fix brightness level not retained over reboot
drm/xe/guc/tlb: Flush g2h worker in case of tlb timeout
drm/xe/ufence: Flush xe ordered_wq in case of ufence timeout
drm/xe: Move LNL scheduling WA to xe_device.h
drm/xe: Use the filelist from drm for ccs_mode change
...
This commit is contained in:
@@ -172,8 +172,8 @@ static union acpi_object *amdgpu_atif_call(struct amdgpu_atif *atif,
|
||||
&buffer);
|
||||
obj = (union acpi_object *)buffer.pointer;
|
||||
|
||||
/* Fail if calling the method fails and ATIF is supported */
|
||||
if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
|
||||
/* Fail if calling the method fails */
|
||||
if (ACPI_FAILURE(status)) {
|
||||
DRM_DEBUG_DRIVER("failed to evaluate ATIF got %s\n",
|
||||
acpi_format_exception(status));
|
||||
kfree(obj);
|
||||
|
||||
@@ -402,7 +402,7 @@ static ssize_t amdgpu_debugfs_gprwave_read(struct file *f, char __user *buf, siz
|
||||
int r;
|
||||
uint32_t *data, x;
|
||||
|
||||
if (size & 0x3 || *pos & 0x3)
|
||||
if (size > 4096 || size & 0x3 || *pos & 0x3)
|
||||
return -EINVAL;
|
||||
|
||||
r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
|
||||
@@ -1648,7 +1648,7 @@ int amdgpu_debugfs_regs_init(struct amdgpu_device *adev)
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(debugfs_regs); i++) {
|
||||
ent = debugfs_create_file(debugfs_regs_names[i],
|
||||
S_IFREG | 0444, root,
|
||||
S_IFREG | 0400, root,
|
||||
adev, debugfs_regs[i]);
|
||||
if (!i && !IS_ERR_OR_NULL(ent))
|
||||
i_size_write(ent->d_inode, adev->rmmio_size);
|
||||
@@ -2100,11 +2100,11 @@ int amdgpu_debugfs_init(struct amdgpu_device *adev)
|
||||
amdgpu_securedisplay_debugfs_init(adev);
|
||||
amdgpu_fw_attestation_debugfs_init(adev);
|
||||
|
||||
debugfs_create_file("amdgpu_evict_vram", 0444, root, adev,
|
||||
debugfs_create_file("amdgpu_evict_vram", 0400, root, adev,
|
||||
&amdgpu_evict_vram_fops);
|
||||
debugfs_create_file("amdgpu_evict_gtt", 0444, root, adev,
|
||||
debugfs_create_file("amdgpu_evict_gtt", 0400, root, adev,
|
||||
&amdgpu_evict_gtt_fops);
|
||||
debugfs_create_file("amdgpu_test_ib", 0444, root, adev,
|
||||
debugfs_create_file("amdgpu_test_ib", 0400, root, adev,
|
||||
&amdgpu_debugfs_test_ib_fops);
|
||||
debugfs_create_file("amdgpu_vm_info", 0444, root, adev,
|
||||
&amdgpu_debugfs_vm_info_fops);
|
||||
|
||||
@@ -482,7 +482,7 @@ static bool __aqua_vanjaram_is_valid_mode(struct amdgpu_xcp_mgr *xcp_mgr,
|
||||
case AMDGPU_SPX_PARTITION_MODE:
|
||||
return adev->gmc.num_mem_partitions == 1 && num_xcc > 0;
|
||||
case AMDGPU_DPX_PARTITION_MODE:
|
||||
return adev->gmc.num_mem_partitions != 8 && (num_xcc % 4) == 0;
|
||||
return adev->gmc.num_mem_partitions <= 2 && (num_xcc % 4) == 0;
|
||||
case AMDGPU_TPX_PARTITION_MODE:
|
||||
return (adev->gmc.num_mem_partitions == 1 ||
|
||||
adev->gmc.num_mem_partitions == 3) &&
|
||||
|
||||
@@ -9429,6 +9429,7 @@ static void amdgpu_dm_commit_streams(struct drm_atomic_state *state,
|
||||
bool mode_set_reset_required = false;
|
||||
u32 i;
|
||||
struct dc_commit_streams_params params = {dc_state->streams, dc_state->stream_count};
|
||||
bool set_backlight_level = false;
|
||||
|
||||
/* Disable writeback */
|
||||
for_each_old_connector_in_state(state, connector, old_con_state, i) {
|
||||
@@ -9548,6 +9549,7 @@ static void amdgpu_dm_commit_streams(struct drm_atomic_state *state,
|
||||
acrtc->hw_mode = new_crtc_state->mode;
|
||||
crtc->hwmode = new_crtc_state->mode;
|
||||
mode_set_reset_required = true;
|
||||
set_backlight_level = true;
|
||||
} else if (modereset_required(new_crtc_state)) {
|
||||
drm_dbg_atomic(dev,
|
||||
"Atomic commit: RESET. crtc id %d:[%p]\n",
|
||||
@@ -9599,6 +9601,19 @@ static void amdgpu_dm_commit_streams(struct drm_atomic_state *state,
|
||||
acrtc->otg_inst = status->primary_otg_inst;
|
||||
}
|
||||
}
|
||||
|
||||
/* During boot up and resume the DC layer will reset the panel brightness
|
||||
* to fix a flicker issue.
|
||||
* It will cause the dm->actual_brightness is not the current panel brightness
|
||||
* level. (the dm->brightness is the correct panel level)
|
||||
* So we set the backlight level with dm->brightness value after set mode
|
||||
*/
|
||||
if (set_backlight_level) {
|
||||
for (i = 0; i < dm->num_of_edps; i++) {
|
||||
if (dm->backlight_dev[i])
|
||||
amdgpu_dm_backlight_set_level(dm, i, dm->brightness[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void dm_set_writeback(struct amdgpu_display_manager *dm,
|
||||
|
||||
@@ -3127,7 +3127,9 @@ static enum bp_result bios_parser_get_vram_info(
|
||||
struct atom_data_revision revision;
|
||||
|
||||
// vram info moved to umc_info for DCN4x
|
||||
if (info && DATA_TABLES(umc_info)) {
|
||||
if (dcb->ctx->dce_version >= DCN_VERSION_4_01 &&
|
||||
dcb->ctx->dce_version < DCN_VERSION_MAX &&
|
||||
info && DATA_TABLES(umc_info)) {
|
||||
header = GET_IMAGE(struct atom_common_table_header,
|
||||
DATA_TABLES(umc_info));
|
||||
|
||||
|
||||
@@ -1259,26 +1259,33 @@ static int smu_sw_init(void *handle)
|
||||
smu->watermarks_bitmap = 0;
|
||||
smu->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
|
||||
smu->default_power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
|
||||
smu->user_dpm_profile.user_workload_mask = 0;
|
||||
|
||||
atomic_set(&smu->smu_power.power_gate.vcn_gated, 1);
|
||||
atomic_set(&smu->smu_power.power_gate.jpeg_gated, 1);
|
||||
atomic_set(&smu->smu_power.power_gate.vpe_gated, 1);
|
||||
atomic_set(&smu->smu_power.power_gate.umsch_mm_gated, 1);
|
||||
|
||||
smu->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT] = 0;
|
||||
smu->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D] = 1;
|
||||
smu->workload_prority[PP_SMC_POWER_PROFILE_POWERSAVING] = 2;
|
||||
smu->workload_prority[PP_SMC_POWER_PROFILE_VIDEO] = 3;
|
||||
smu->workload_prority[PP_SMC_POWER_PROFILE_VR] = 4;
|
||||
smu->workload_prority[PP_SMC_POWER_PROFILE_COMPUTE] = 5;
|
||||
smu->workload_prority[PP_SMC_POWER_PROFILE_CUSTOM] = 6;
|
||||
smu->workload_priority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT] = 0;
|
||||
smu->workload_priority[PP_SMC_POWER_PROFILE_FULLSCREEN3D] = 1;
|
||||
smu->workload_priority[PP_SMC_POWER_PROFILE_POWERSAVING] = 2;
|
||||
smu->workload_priority[PP_SMC_POWER_PROFILE_VIDEO] = 3;
|
||||
smu->workload_priority[PP_SMC_POWER_PROFILE_VR] = 4;
|
||||
smu->workload_priority[PP_SMC_POWER_PROFILE_COMPUTE] = 5;
|
||||
smu->workload_priority[PP_SMC_POWER_PROFILE_CUSTOM] = 6;
|
||||
|
||||
if (smu->is_apu ||
|
||||
!smu_is_workload_profile_available(smu, PP_SMC_POWER_PROFILE_FULLSCREEN3D))
|
||||
smu->workload_mask = 1 << smu->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT];
|
||||
else
|
||||
smu->workload_mask = 1 << smu->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D];
|
||||
!smu_is_workload_profile_available(smu, PP_SMC_POWER_PROFILE_FULLSCREEN3D)) {
|
||||
smu->driver_workload_mask =
|
||||
1 << smu->workload_priority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT];
|
||||
} else {
|
||||
smu->driver_workload_mask =
|
||||
1 << smu->workload_priority[PP_SMC_POWER_PROFILE_FULLSCREEN3D];
|
||||
smu->default_power_profile_mode = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
|
||||
}
|
||||
|
||||
smu->workload_mask = smu->driver_workload_mask |
|
||||
smu->user_dpm_profile.user_workload_mask;
|
||||
smu->workload_setting[0] = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
|
||||
smu->workload_setting[1] = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
|
||||
smu->workload_setting[2] = PP_SMC_POWER_PROFILE_POWERSAVING;
|
||||
@@ -2348,17 +2355,20 @@ static int smu_switch_power_profile(void *handle,
|
||||
return -EINVAL;
|
||||
|
||||
if (!en) {
|
||||
smu->workload_mask &= ~(1 << smu->workload_prority[type]);
|
||||
smu->driver_workload_mask &= ~(1 << smu->workload_priority[type]);
|
||||
index = fls(smu->workload_mask);
|
||||
index = index > 0 && index <= WORKLOAD_POLICY_MAX ? index - 1 : 0;
|
||||
workload[0] = smu->workload_setting[index];
|
||||
} else {
|
||||
smu->workload_mask |= (1 << smu->workload_prority[type]);
|
||||
smu->driver_workload_mask |= (1 << smu->workload_priority[type]);
|
||||
index = fls(smu->workload_mask);
|
||||
index = index <= WORKLOAD_POLICY_MAX ? index - 1 : 0;
|
||||
workload[0] = smu->workload_setting[index];
|
||||
}
|
||||
|
||||
smu->workload_mask = smu->driver_workload_mask |
|
||||
smu->user_dpm_profile.user_workload_mask;
|
||||
|
||||
if (smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL &&
|
||||
smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM)
|
||||
smu_bump_power_profile_mode(smu, workload, 0);
|
||||
@@ -3049,12 +3059,23 @@ static int smu_set_power_profile_mode(void *handle,
|
||||
uint32_t param_size)
|
||||
{
|
||||
struct smu_context *smu = handle;
|
||||
int ret;
|
||||
|
||||
if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled ||
|
||||
!smu->ppt_funcs->set_power_profile_mode)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return smu_bump_power_profile_mode(smu, param, param_size);
|
||||
if (smu->user_dpm_profile.user_workload_mask &
|
||||
(1 << smu->workload_priority[param[param_size]]))
|
||||
return 0;
|
||||
|
||||
smu->user_dpm_profile.user_workload_mask =
|
||||
(1 << smu->workload_priority[param[param_size]]);
|
||||
smu->workload_mask = smu->user_dpm_profile.user_workload_mask |
|
||||
smu->driver_workload_mask;
|
||||
ret = smu_bump_power_profile_mode(smu, param, param_size);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int smu_get_fan_control_mode(void *handle, u32 *fan_mode)
|
||||
|
||||
@@ -240,6 +240,7 @@ struct smu_user_dpm_profile {
|
||||
/* user clock state information */
|
||||
uint32_t clk_mask[SMU_CLK_COUNT];
|
||||
uint32_t clk_dependency;
|
||||
uint32_t user_workload_mask;
|
||||
};
|
||||
|
||||
#define SMU_TABLE_INIT(tables, table_id, s, a, d) \
|
||||
@@ -557,7 +558,8 @@ struct smu_context {
|
||||
bool disable_uclk_switch;
|
||||
|
||||
uint32_t workload_mask;
|
||||
uint32_t workload_prority[WORKLOAD_POLICY_MAX];
|
||||
uint32_t driver_workload_mask;
|
||||
uint32_t workload_priority[WORKLOAD_POLICY_MAX];
|
||||
uint32_t workload_setting[WORKLOAD_POLICY_MAX];
|
||||
uint32_t power_profile_mode;
|
||||
uint32_t default_power_profile_mode;
|
||||
|
||||
@@ -1455,7 +1455,6 @@ static int arcturus_set_power_profile_mode(struct smu_context *smu,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
||||
if ((profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) &&
|
||||
(smu->smc_fw_version >= 0x360d00)) {
|
||||
if (size != 10)
|
||||
@@ -1523,14 +1522,14 @@ static int arcturus_set_power_profile_mode(struct smu_context *smu,
|
||||
|
||||
ret = smu_cmn_send_smc_msg_with_param(smu,
|
||||
SMU_MSG_SetWorkloadMask,
|
||||
1 << workload_type,
|
||||
smu->workload_mask,
|
||||
NULL);
|
||||
if (ret) {
|
||||
dev_err(smu->adev->dev, "Fail to set workload type %d\n", workload_type);
|
||||
return ret;
|
||||
}
|
||||
|
||||
smu->power_profile_mode = profile_mode;
|
||||
smu_cmn_assign_power_profile(smu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2081,10 +2081,13 @@ static int navi10_set_power_profile_mode(struct smu_context *smu, long *input, u
|
||||
smu->power_profile_mode);
|
||||
if (workload_type < 0)
|
||||
return -EINVAL;
|
||||
|
||||
ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
|
||||
1 << workload_type, NULL);
|
||||
smu->workload_mask, NULL);
|
||||
if (ret)
|
||||
dev_err(smu->adev->dev, "[%s] Failed to set work load mask!", __func__);
|
||||
else
|
||||
smu_cmn_assign_power_profile(smu);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1786,10 +1786,13 @@ static int sienna_cichlid_set_power_profile_mode(struct smu_context *smu, long *
|
||||
smu->power_profile_mode);
|
||||
if (workload_type < 0)
|
||||
return -EINVAL;
|
||||
|
||||
ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
|
||||
1 << workload_type, NULL);
|
||||
smu->workload_mask, NULL);
|
||||
if (ret)
|
||||
dev_err(smu->adev->dev, "[%s] Failed to set work load mask!", __func__);
|
||||
else
|
||||
smu_cmn_assign_power_profile(smu);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1079,7 +1079,7 @@ static int vangogh_set_power_profile_mode(struct smu_context *smu, long *input,
|
||||
}
|
||||
|
||||
ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_ActiveProcessNotify,
|
||||
1 << workload_type,
|
||||
smu->workload_mask,
|
||||
NULL);
|
||||
if (ret) {
|
||||
dev_err_once(smu->adev->dev, "Fail to set workload type %d\n",
|
||||
@@ -1087,7 +1087,7 @@ static int vangogh_set_power_profile_mode(struct smu_context *smu, long *input,
|
||||
return ret;
|
||||
}
|
||||
|
||||
smu->power_profile_mode = profile_mode;
|
||||
smu_cmn_assign_power_profile(smu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -890,14 +890,14 @@ static int renoir_set_power_profile_mode(struct smu_context *smu, long *input, u
|
||||
}
|
||||
|
||||
ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_ActiveProcessNotify,
|
||||
1 << workload_type,
|
||||
smu->workload_mask,
|
||||
NULL);
|
||||
if (ret) {
|
||||
dev_err_once(smu->adev->dev, "Fail to set workload type %d\n", workload_type);
|
||||
return ret;
|
||||
}
|
||||
|
||||
smu->power_profile_mode = profile_mode;
|
||||
smu_cmn_assign_power_profile(smu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2485,7 +2485,7 @@ static int smu_v13_0_0_set_power_profile_mode(struct smu_context *smu,
|
||||
DpmActivityMonitorCoeffInt_t *activity_monitor =
|
||||
&(activity_monitor_external.DpmActivityMonitorCoeffInt);
|
||||
int workload_type, ret = 0;
|
||||
u32 workload_mask, selected_workload_mask;
|
||||
u32 workload_mask;
|
||||
|
||||
smu->power_profile_mode = input[size];
|
||||
|
||||
@@ -2552,7 +2552,7 @@ static int smu_v13_0_0_set_power_profile_mode(struct smu_context *smu,
|
||||
if (workload_type < 0)
|
||||
return -EINVAL;
|
||||
|
||||
selected_workload_mask = workload_mask = 1 << workload_type;
|
||||
workload_mask = 1 << workload_type;
|
||||
|
||||
/* Add optimizations for SMU13.0.0/10. Reuse the power saving profile */
|
||||
if ((amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(13, 0, 0) &&
|
||||
@@ -2567,12 +2567,22 @@ static int smu_v13_0_0_set_power_profile_mode(struct smu_context *smu,
|
||||
workload_mask |= 1 << workload_type;
|
||||
}
|
||||
|
||||
smu->workload_mask |= workload_mask;
|
||||
ret = smu_cmn_send_smc_msg_with_param(smu,
|
||||
SMU_MSG_SetWorkloadMask,
|
||||
workload_mask,
|
||||
smu->workload_mask,
|
||||
NULL);
|
||||
if (!ret)
|
||||
smu->workload_mask = selected_workload_mask;
|
||||
if (!ret) {
|
||||
smu_cmn_assign_power_profile(smu);
|
||||
if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_POWERSAVING) {
|
||||
workload_type = smu_cmn_to_asic_specific_index(smu,
|
||||
CMN2ASIC_MAPPING_WORKLOAD,
|
||||
PP_SMC_POWER_PROFILE_FULLSCREEN3D);
|
||||
smu->power_profile_mode = smu->workload_mask & (1 << workload_type)
|
||||
? PP_SMC_POWER_PROFILE_FULLSCREEN3D
|
||||
: PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -2499,13 +2499,14 @@ static int smu_v13_0_7_set_power_profile_mode(struct smu_context *smu, long *inp
|
||||
smu->power_profile_mode);
|
||||
if (workload_type < 0)
|
||||
return -EINVAL;
|
||||
|
||||
ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
|
||||
1 << workload_type, NULL);
|
||||
smu->workload_mask, NULL);
|
||||
|
||||
if (ret)
|
||||
dev_err(smu->adev->dev, "[%s] Failed to set work load mask!", __func__);
|
||||
else
|
||||
smu->workload_mask = (1 << workload_type);
|
||||
smu_cmn_assign_power_profile(smu);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -367,54 +367,6 @@ static int smu_v14_0_2_store_powerplay_table(struct smu_context *smu)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef atom_smc_dpm_info_table_14_0_0
|
||||
struct atom_smc_dpm_info_table_14_0_0 {
|
||||
struct atom_common_table_header table_header;
|
||||
BoardTable_t BoardTable;
|
||||
};
|
||||
#endif
|
||||
|
||||
static int smu_v14_0_2_append_powerplay_table(struct smu_context *smu)
|
||||
{
|
||||
struct smu_table_context *table_context = &smu->smu_table;
|
||||
PPTable_t *smc_pptable = table_context->driver_pptable;
|
||||
struct atom_smc_dpm_info_table_14_0_0 *smc_dpm_table;
|
||||
BoardTable_t *BoardTable = &smc_pptable->BoardTable;
|
||||
int index, ret;
|
||||
|
||||
index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
|
||||
smc_dpm_info);
|
||||
|
||||
ret = amdgpu_atombios_get_data_table(smu->adev, index, NULL, NULL, NULL,
|
||||
(uint8_t **)&smc_dpm_table);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
memcpy(BoardTable, &smc_dpm_table->BoardTable, sizeof(BoardTable_t));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int smu_v14_0_2_get_pptable_from_pmfw(struct smu_context *smu,
|
||||
void **table,
|
||||
uint32_t *size)
|
||||
{
|
||||
struct smu_table_context *smu_table = &smu->smu_table;
|
||||
void *combo_pptable = smu_table->combo_pptable;
|
||||
int ret = 0;
|
||||
|
||||
ret = smu_cmn_get_combo_pptable(smu);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*table = combo_pptable;
|
||||
*size = sizeof(struct smu_14_0_powerplay_table);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int smu_v14_0_2_get_pptable_from_pmfw(struct smu_context *smu,
|
||||
void **table,
|
||||
uint32_t *size)
|
||||
@@ -436,16 +388,12 @@ static int smu_v14_0_2_get_pptable_from_pmfw(struct smu_context *smu,
|
||||
static int smu_v14_0_2_setup_pptable(struct smu_context *smu)
|
||||
{
|
||||
struct smu_table_context *smu_table = &smu->smu_table;
|
||||
struct amdgpu_device *adev = smu->adev;
|
||||
int ret = 0;
|
||||
|
||||
if (amdgpu_sriov_vf(smu->adev))
|
||||
return 0;
|
||||
|
||||
if (!adev->scpm_enabled)
|
||||
ret = smu_v14_0_setup_pptable(smu);
|
||||
else
|
||||
ret = smu_v14_0_2_get_pptable_from_pmfw(smu,
|
||||
ret = smu_v14_0_2_get_pptable_from_pmfw(smu,
|
||||
&smu_table->power_play_table,
|
||||
&smu_table->power_play_table_size);
|
||||
if (ret)
|
||||
@@ -455,16 +403,6 @@ static int smu_v14_0_2_setup_pptable(struct smu_context *smu)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* With SCPM enabled, the operation below will be handled
|
||||
* by PSP. Driver involvment is unnecessary and useless.
|
||||
*/
|
||||
if (!adev->scpm_enabled) {
|
||||
ret = smu_v14_0_2_append_powerplay_table(smu);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = smu_v14_0_2_check_powerplay_table(smu);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -1869,12 +1807,11 @@ static int smu_v14_0_2_set_power_profile_mode(struct smu_context *smu,
|
||||
if (workload_type < 0)
|
||||
return -EINVAL;
|
||||
|
||||
ret = smu_cmn_send_smc_msg_with_param(smu,
|
||||
SMU_MSG_SetWorkloadMask,
|
||||
1 << workload_type,
|
||||
NULL);
|
||||
ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
|
||||
smu->workload_mask, NULL);
|
||||
|
||||
if (!ret)
|
||||
smu->workload_mask = 1 << workload_type;
|
||||
smu_cmn_assign_power_profile(smu);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -2799,7 +2736,6 @@ static const struct pptable_funcs smu_v14_0_2_ppt_funcs = {
|
||||
.check_fw_status = smu_v14_0_check_fw_status,
|
||||
.setup_pptable = smu_v14_0_2_setup_pptable,
|
||||
.check_fw_version = smu_v14_0_check_fw_version,
|
||||
.write_pptable = smu_cmn_write_pptable,
|
||||
.set_driver_table_location = smu_v14_0_set_driver_table_location,
|
||||
.system_features_control = smu_v14_0_system_features_control,
|
||||
.set_allowed_mask = smu_v14_0_set_allowed_mask,
|
||||
|
||||
@@ -1138,6 +1138,14 @@ int smu_cmn_set_mp1_state(struct smu_context *smu,
|
||||
return ret;
|
||||
}
|
||||
|
||||
void smu_cmn_assign_power_profile(struct smu_context *smu)
|
||||
{
|
||||
uint32_t index;
|
||||
index = fls(smu->workload_mask);
|
||||
index = index > 0 && index <= WORKLOAD_POLICY_MAX ? index - 1 : 0;
|
||||
smu->power_profile_mode = smu->workload_setting[index];
|
||||
}
|
||||
|
||||
bool smu_cmn_is_audio_func_enabled(struct amdgpu_device *adev)
|
||||
{
|
||||
struct pci_dev *p = NULL;
|
||||
|
||||
@@ -130,6 +130,8 @@ void smu_cmn_init_soft_gpu_metrics(void *table, uint8_t frev, uint8_t crev);
|
||||
int smu_cmn_set_mp1_state(struct smu_context *smu,
|
||||
enum pp_mp1_state mp1_state);
|
||||
|
||||
void smu_cmn_assign_power_profile(struct smu_context *smu);
|
||||
|
||||
/*
|
||||
* Helper function to make sysfs_emit_at() happy. Align buf to
|
||||
* the current page boundary and record the offset.
|
||||
|
||||
@@ -403,7 +403,6 @@ static const struct dmi_system_id orientation_data[] = {
|
||||
}, { /* Lenovo Yoga Tab 3 X90F */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"),
|
||||
DMI_MATCH(DMI_PRODUCT_VERSION, "Blade3-10A-001"),
|
||||
},
|
||||
.driver_data = (void *)&lcd1600x2560_rightside_up,
|
||||
|
||||
@@ -17,10 +17,14 @@
|
||||
|
||||
#include <drm/drm_auth.h>
|
||||
#include <drm/drm_managed.h>
|
||||
|
||||
#include <linux/bug.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/xarray.h>
|
||||
@@ -354,6 +358,10 @@ int pvr_context_create(struct pvr_file *pvr_file, struct drm_pvr_ioctl_create_co
|
||||
return err;
|
||||
}
|
||||
|
||||
spin_lock(&pvr_dev->ctx_list_lock);
|
||||
list_add_tail(&ctx->file_link, &pvr_file->contexts);
|
||||
spin_unlock(&pvr_dev->ctx_list_lock);
|
||||
|
||||
return 0;
|
||||
|
||||
err_destroy_fw_obj:
|
||||
@@ -380,6 +388,11 @@ pvr_context_release(struct kref *ref_count)
|
||||
container_of(ref_count, struct pvr_context, ref_count);
|
||||
struct pvr_device *pvr_dev = ctx->pvr_dev;
|
||||
|
||||
WARN_ON(in_interrupt());
|
||||
spin_lock(&pvr_dev->ctx_list_lock);
|
||||
list_del(&ctx->file_link);
|
||||
spin_unlock(&pvr_dev->ctx_list_lock);
|
||||
|
||||
xa_erase(&pvr_dev->ctx_ids, ctx->ctx_id);
|
||||
pvr_context_destroy_queues(ctx);
|
||||
pvr_fw_object_destroy(ctx->fw_obj);
|
||||
@@ -437,11 +450,30 @@ pvr_context_destroy(struct pvr_file *pvr_file, u32 handle)
|
||||
*/
|
||||
void pvr_destroy_contexts_for_file(struct pvr_file *pvr_file)
|
||||
{
|
||||
struct pvr_device *pvr_dev = pvr_file->pvr_dev;
|
||||
struct pvr_context *ctx;
|
||||
unsigned long handle;
|
||||
|
||||
xa_for_each(&pvr_file->ctx_handles, handle, ctx)
|
||||
pvr_context_destroy(pvr_file, handle);
|
||||
|
||||
spin_lock(&pvr_dev->ctx_list_lock);
|
||||
ctx = list_first_entry(&pvr_file->contexts, struct pvr_context, file_link);
|
||||
|
||||
while (!list_entry_is_head(ctx, &pvr_file->contexts, file_link)) {
|
||||
list_del_init(&ctx->file_link);
|
||||
|
||||
if (pvr_context_get_if_referenced(ctx)) {
|
||||
spin_unlock(&pvr_dev->ctx_list_lock);
|
||||
|
||||
pvr_vm_unmap_all(ctx->vm_ctx);
|
||||
|
||||
pvr_context_put(ctx);
|
||||
spin_lock(&pvr_dev->ctx_list_lock);
|
||||
}
|
||||
ctx = list_first_entry(&pvr_file->contexts, struct pvr_context, file_link);
|
||||
}
|
||||
spin_unlock(&pvr_dev->ctx_list_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -451,6 +483,7 @@ void pvr_destroy_contexts_for_file(struct pvr_file *pvr_file)
|
||||
void pvr_context_device_init(struct pvr_device *pvr_dev)
|
||||
{
|
||||
xa_init_flags(&pvr_dev->ctx_ids, XA_FLAGS_ALLOC1);
|
||||
spin_lock_init(&pvr_dev->ctx_list_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -85,6 +85,9 @@ struct pvr_context {
|
||||
/** @compute: Transfer queue. */
|
||||
struct pvr_queue *transfer;
|
||||
} queues;
|
||||
|
||||
/** @file_link: pvr_file PVR context list link. */
|
||||
struct list_head file_link;
|
||||
};
|
||||
|
||||
static __always_inline struct pvr_queue *
|
||||
@@ -123,6 +126,24 @@ pvr_context_get(struct pvr_context *ctx)
|
||||
return ctx;
|
||||
}
|
||||
|
||||
/**
|
||||
* pvr_context_get_if_referenced() - Take an additional reference on a still
|
||||
* referenced context.
|
||||
* @ctx: Context pointer.
|
||||
*
|
||||
* Call pvr_context_put() to release.
|
||||
*
|
||||
* Returns:
|
||||
* * True on success, or
|
||||
* * false if no context pointer passed, or the context wasn't still
|
||||
* * referenced.
|
||||
*/
|
||||
static __always_inline bool
|
||||
pvr_context_get_if_referenced(struct pvr_context *ctx)
|
||||
{
|
||||
return ctx != NULL && kref_get_unless_zero(&ctx->ref_count) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* pvr_context_lookup() - Lookup context pointer from handle and file.
|
||||
* @pvr_file: Pointer to pvr_file structure.
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/math.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/spinlock_types.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/wait.h>
|
||||
@@ -293,6 +294,12 @@ struct pvr_device {
|
||||
|
||||
/** @sched_wq: Workqueue for schedulers. */
|
||||
struct workqueue_struct *sched_wq;
|
||||
|
||||
/**
|
||||
* @ctx_list_lock: Lock to be held when accessing the context list in
|
||||
* struct pvr_file.
|
||||
*/
|
||||
spinlock_t ctx_list_lock;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -344,6 +351,9 @@ struct pvr_file {
|
||||
* This array is used to allocate handles returned to userspace.
|
||||
*/
|
||||
struct xarray vm_ctx_handles;
|
||||
|
||||
/** @contexts: PVR context list. */
|
||||
struct list_head contexts;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <linux/export.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
@@ -1326,6 +1327,8 @@ pvr_drm_driver_open(struct drm_device *drm_dev, struct drm_file *file)
|
||||
*/
|
||||
pvr_file->pvr_dev = pvr_dev;
|
||||
|
||||
INIT_LIST_HEAD(&pvr_file->contexts);
|
||||
|
||||
xa_init_flags(&pvr_file->ctx_handles, XA_FLAGS_ALLOC1);
|
||||
xa_init_flags(&pvr_file->free_list_handles, XA_FLAGS_ALLOC1);
|
||||
xa_init_flags(&pvr_file->hwrt_handles, XA_FLAGS_ALLOC1);
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <drm/drm_gem.h>
|
||||
#include <drm/drm_gpuvm.h>
|
||||
|
||||
#include <linux/bug.h>
|
||||
#include <linux/container_of.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/errno.h>
|
||||
@@ -597,12 +598,26 @@ pvr_vm_create_context(struct pvr_device *pvr_dev, bool is_userspace_context)
|
||||
}
|
||||
|
||||
/**
|
||||
* pvr_vm_context_release() - Teardown a VM context.
|
||||
* @ref_count: Pointer to reference counter of the VM context.
|
||||
* pvr_vm_unmap_all() - Unmap all mappings associated with a VM context.
|
||||
* @vm_ctx: Target VM context.
|
||||
*
|
||||
* This function ensures that no mappings are left dangling by unmapping them
|
||||
* all in order of ascending device-virtual address.
|
||||
*/
|
||||
void
|
||||
pvr_vm_unmap_all(struct pvr_vm_context *vm_ctx)
|
||||
{
|
||||
WARN_ON(pvr_vm_unmap(vm_ctx, vm_ctx->gpuvm_mgr.mm_start,
|
||||
vm_ctx->gpuvm_mgr.mm_range));
|
||||
}
|
||||
|
||||
/**
|
||||
* pvr_vm_context_release() - Teardown a VM context.
|
||||
* @ref_count: Pointer to reference counter of the VM context.
|
||||
*
|
||||
* This function also ensures that no mappings are left dangling by calling
|
||||
* pvr_vm_unmap_all.
|
||||
*/
|
||||
static void
|
||||
pvr_vm_context_release(struct kref *ref_count)
|
||||
{
|
||||
@@ -612,8 +627,7 @@ pvr_vm_context_release(struct kref *ref_count)
|
||||
if (vm_ctx->fw_mem_ctx_obj)
|
||||
pvr_fw_object_destroy(vm_ctx->fw_mem_ctx_obj);
|
||||
|
||||
WARN_ON(pvr_vm_unmap(vm_ctx, vm_ctx->gpuvm_mgr.mm_start,
|
||||
vm_ctx->gpuvm_mgr.mm_range));
|
||||
pvr_vm_unmap_all(vm_ctx);
|
||||
|
||||
pvr_mmu_context_destroy(vm_ctx->mmu_ctx);
|
||||
drm_gem_private_object_fini(&vm_ctx->dummy_gem);
|
||||
|
||||
@@ -39,6 +39,7 @@ int pvr_vm_map(struct pvr_vm_context *vm_ctx,
|
||||
struct pvr_gem_object *pvr_obj, u64 pvr_obj_offset,
|
||||
u64 device_addr, u64 size);
|
||||
int pvr_vm_unmap(struct pvr_vm_context *vm_ctx, u64 device_addr, u64 size);
|
||||
void pvr_vm_unmap_all(struct pvr_vm_context *vm_ctx);
|
||||
|
||||
dma_addr_t pvr_vm_get_page_table_root_addr(struct pvr_vm_context *vm_ctx);
|
||||
struct dma_resv *pvr_vm_get_dma_resv(struct pvr_vm_context *vm_ctx);
|
||||
|
||||
@@ -390,11 +390,15 @@ int panthor_device_mmap_io(struct panthor_device *ptdev, struct vm_area_struct *
|
||||
{
|
||||
u64 offset = (u64)vma->vm_pgoff << PAGE_SHIFT;
|
||||
|
||||
if ((vma->vm_flags & VM_SHARED) == 0)
|
||||
return -EINVAL;
|
||||
|
||||
switch (offset) {
|
||||
case DRM_PANTHOR_USER_FLUSH_ID_MMIO_OFFSET:
|
||||
if (vma->vm_end - vma->vm_start != PAGE_SIZE ||
|
||||
(vma->vm_flags & (VM_WRITE | VM_EXEC)))
|
||||
return -EINVAL;
|
||||
vm_flags_clear(vma, VM_MAYWRITE);
|
||||
|
||||
break;
|
||||
|
||||
|
||||
@@ -1580,7 +1580,9 @@ panthor_vm_pool_get_vm(struct panthor_vm_pool *pool, u32 handle)
|
||||
{
|
||||
struct panthor_vm *vm;
|
||||
|
||||
xa_lock(&pool->xa);
|
||||
vm = panthor_vm_get(xa_load(&pool->xa, handle));
|
||||
xa_unlock(&pool->xa);
|
||||
|
||||
return vm;
|
||||
}
|
||||
|
||||
@@ -517,7 +517,7 @@
|
||||
* [4-6] RSVD
|
||||
* [7] Disabled
|
||||
*/
|
||||
#define CCS_MODE XE_REG(0x14804)
|
||||
#define CCS_MODE XE_REG(0x14804, XE_REG_OPTION_MASKED)
|
||||
#define CCS_MODE_CSLICE_0_3_MASK REG_GENMASK(11, 0) /* 3 bits per cslice */
|
||||
#define CCS_MODE_CSLICE_MASK 0x7 /* CCS0-3 + rsvd */
|
||||
#define CCS_MODE_CSLICE_WIDTH ilog2(CCS_MODE_CSLICE_MASK + 1)
|
||||
|
||||
@@ -87,10 +87,6 @@ static int xe_file_open(struct drm_device *dev, struct drm_file *file)
|
||||
mutex_init(&xef->exec_queue.lock);
|
||||
xa_init_flags(&xef->exec_queue.xa, XA_FLAGS_ALLOC1);
|
||||
|
||||
spin_lock(&xe->clients.lock);
|
||||
xe->clients.count++;
|
||||
spin_unlock(&xe->clients.lock);
|
||||
|
||||
file->driver_priv = xef;
|
||||
kref_init(&xef->refcount);
|
||||
|
||||
@@ -107,17 +103,12 @@ static int xe_file_open(struct drm_device *dev, struct drm_file *file)
|
||||
static void xe_file_destroy(struct kref *ref)
|
||||
{
|
||||
struct xe_file *xef = container_of(ref, struct xe_file, refcount);
|
||||
struct xe_device *xe = xef->xe;
|
||||
|
||||
xa_destroy(&xef->exec_queue.xa);
|
||||
mutex_destroy(&xef->exec_queue.lock);
|
||||
xa_destroy(&xef->vm.xa);
|
||||
mutex_destroy(&xef->vm.lock);
|
||||
|
||||
spin_lock(&xe->clients.lock);
|
||||
xe->clients.count--;
|
||||
spin_unlock(&xe->clients.lock);
|
||||
|
||||
xe_drm_client_put(xef->client);
|
||||
kfree(xef->process_name);
|
||||
kfree(xef);
|
||||
@@ -333,7 +324,6 @@ struct xe_device *xe_device_create(struct pci_dev *pdev,
|
||||
xe->info.force_execlist = xe_modparam.force_execlist;
|
||||
|
||||
spin_lock_init(&xe->irq.lock);
|
||||
spin_lock_init(&xe->clients.lock);
|
||||
|
||||
init_waitqueue_head(&xe->ufence_wq);
|
||||
|
||||
|
||||
@@ -178,4 +178,18 @@ void xe_device_declare_wedged(struct xe_device *xe);
|
||||
struct xe_file *xe_file_get(struct xe_file *xef);
|
||||
void xe_file_put(struct xe_file *xef);
|
||||
|
||||
/*
|
||||
* Occasionally it is seen that the G2H worker starts running after a delay of more than
|
||||
* a second even after being queued and activated by the Linux workqueue subsystem. This
|
||||
* leads to G2H timeout error. The root cause of issue lies with scheduling latency of
|
||||
* Lunarlake Hybrid CPU. Issue disappears if we disable Lunarlake atom cores from BIOS
|
||||
* and this is beyond xe kmd.
|
||||
*
|
||||
* TODO: Drop this change once workqueue scheduling delay issue is fixed on LNL Hybrid CPU.
|
||||
*/
|
||||
#define LNL_FLUSH_WORKQUEUE(wq__) \
|
||||
flush_workqueue(wq__)
|
||||
#define LNL_FLUSH_WORK(wrk__) \
|
||||
flush_work(wrk__)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -353,15 +353,6 @@ struct xe_device {
|
||||
struct workqueue_struct *wq;
|
||||
} sriov;
|
||||
|
||||
/** @clients: drm clients info */
|
||||
struct {
|
||||
/** @clients.lock: Protects drm clients info */
|
||||
spinlock_t lock;
|
||||
|
||||
/** @clients.count: number of drm clients */
|
||||
u64 count;
|
||||
} clients;
|
||||
|
||||
/** @usm: unified memory state */
|
||||
struct {
|
||||
/** @usm.asid: convert a ASID to VM */
|
||||
|
||||
@@ -132,12 +132,16 @@ int xe_exec_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
|
||||
if (XE_IOCTL_DBG(xe, !q))
|
||||
return -ENOENT;
|
||||
|
||||
if (XE_IOCTL_DBG(xe, q->flags & EXEC_QUEUE_FLAG_VM))
|
||||
return -EINVAL;
|
||||
if (XE_IOCTL_DBG(xe, q->flags & EXEC_QUEUE_FLAG_VM)) {
|
||||
err = -EINVAL;
|
||||
goto err_exec_queue;
|
||||
}
|
||||
|
||||
if (XE_IOCTL_DBG(xe, args->num_batch_buffer &&
|
||||
q->width != args->num_batch_buffer))
|
||||
return -EINVAL;
|
||||
q->width != args->num_batch_buffer)) {
|
||||
err = -EINVAL;
|
||||
goto err_exec_queue;
|
||||
}
|
||||
|
||||
if (XE_IOCTL_DBG(xe, q->ops->reset_status(q))) {
|
||||
err = -ECANCELED;
|
||||
@@ -220,6 +224,7 @@ int xe_exec_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
|
||||
fence = xe_sync_in_fence_get(syncs, num_syncs, q, vm);
|
||||
if (IS_ERR(fence)) {
|
||||
err = PTR_ERR(fence);
|
||||
xe_vm_unlock(vm);
|
||||
goto err_unlock_list;
|
||||
}
|
||||
for (i = 0; i < num_syncs; i++)
|
||||
|
||||
@@ -260,8 +260,14 @@ void xe_exec_queue_fini(struct xe_exec_queue *q)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Before releasing our ref to lrc and xef, accumulate our run ticks
|
||||
*/
|
||||
xe_exec_queue_update_run_ticks(q);
|
||||
|
||||
for (i = 0; i < q->width; ++i)
|
||||
xe_lrc_put(q->lrc[i]);
|
||||
|
||||
__xe_exec_queue_free(q);
|
||||
}
|
||||
|
||||
|
||||
@@ -68,6 +68,12 @@ static void __xe_gt_apply_ccs_mode(struct xe_gt *gt, u32 num_engines)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Mask bits need to be set for the register. Though only Xe2+
|
||||
* platforms require setting of mask bits, it won't harm for older
|
||||
* platforms as these bits are unused there.
|
||||
*/
|
||||
mode |= CCS_MODE_CSLICE_0_3_MASK << 16;
|
||||
xe_mmio_write32(gt, CCS_MODE, mode);
|
||||
|
||||
xe_gt_dbg(gt, "CCS_MODE=%x config:%08x, num_engines:%d, num_slices:%d\n",
|
||||
@@ -133,9 +139,10 @@ ccs_mode_store(struct device *kdev, struct device_attribute *attr,
|
||||
}
|
||||
|
||||
/* CCS mode can only be updated when there are no drm clients */
|
||||
spin_lock(&xe->clients.lock);
|
||||
if (xe->clients.count) {
|
||||
spin_unlock(&xe->clients.lock);
|
||||
mutex_lock(&xe->drm.filelist_mutex);
|
||||
if (!list_empty(&xe->drm.filelist)) {
|
||||
mutex_unlock(&xe->drm.filelist_mutex);
|
||||
xe_gt_dbg(gt, "Rejecting compute mode change as there are active drm clients\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
@@ -146,7 +153,7 @@ ccs_mode_store(struct device *kdev, struct device_attribute *attr,
|
||||
xe_gt_reset_async(gt);
|
||||
}
|
||||
|
||||
spin_unlock(&xe->clients.lock);
|
||||
mutex_unlock(&xe->drm.filelist_mutex);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
@@ -387,6 +387,8 @@ static void pf_release_ggtt(struct xe_tile *tile, struct xe_ggtt_node *node)
|
||||
* the xe_ggtt_clear() called by below xe_ggtt_remove_node().
|
||||
*/
|
||||
xe_ggtt_node_remove(node, false);
|
||||
} else {
|
||||
xe_ggtt_node_fini(node);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -442,7 +444,7 @@ static int pf_provision_vf_ggtt(struct xe_gt *gt, unsigned int vfid, u64 size)
|
||||
config->ggtt_region = node;
|
||||
return 0;
|
||||
err:
|
||||
xe_ggtt_node_fini(node);
|
||||
pf_release_ggtt(tile, node);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@@ -72,6 +72,8 @@ static void xe_gt_tlb_fence_timeout(struct work_struct *work)
|
||||
struct xe_device *xe = gt_to_xe(gt);
|
||||
struct xe_gt_tlb_invalidation_fence *fence, *next;
|
||||
|
||||
LNL_FLUSH_WORK(>->uc.guc.ct.g2h_worker);
|
||||
|
||||
spin_lock_irq(>->tlb_invalidation.pending_lock);
|
||||
list_for_each_entry_safe(fence, next,
|
||||
>->tlb_invalidation.pending_fences, link) {
|
||||
|
||||
@@ -897,17 +897,8 @@ static int guc_ct_send_recv(struct xe_guc_ct *ct, const u32 *action, u32 len,
|
||||
|
||||
ret = wait_event_timeout(ct->g2h_fence_wq, g2h_fence.done, HZ);
|
||||
|
||||
/*
|
||||
* Occasionally it is seen that the G2H worker starts running after a delay of more than
|
||||
* a second even after being queued and activated by the Linux workqueue subsystem. This
|
||||
* leads to G2H timeout error. The root cause of issue lies with scheduling latency of
|
||||
* Lunarlake Hybrid CPU. Issue dissappears if we disable Lunarlake atom cores from BIOS
|
||||
* and this is beyond xe kmd.
|
||||
*
|
||||
* TODO: Drop this change once workqueue scheduling delay issue is fixed on LNL Hybrid CPU.
|
||||
*/
|
||||
if (!ret) {
|
||||
flush_work(&ct->g2h_worker);
|
||||
LNL_FLUSH_WORK(&ct->g2h_worker);
|
||||
if (g2h_fence.done) {
|
||||
xe_gt_warn(gt, "G2H fence %u, action %04x, done\n",
|
||||
g2h_fence.seqno, action[0]);
|
||||
|
||||
@@ -745,8 +745,6 @@ static void guc_exec_queue_free_job(struct drm_sched_job *drm_job)
|
||||
{
|
||||
struct xe_sched_job *job = to_xe_sched_job(drm_job);
|
||||
|
||||
xe_exec_queue_update_run_ticks(job->q);
|
||||
|
||||
trace_xe_sched_job_free(job);
|
||||
xe_sched_job_put(job);
|
||||
}
|
||||
|
||||
@@ -155,6 +155,13 @@ int xe_wait_user_fence_ioctl(struct drm_device *dev, void *data,
|
||||
}
|
||||
|
||||
if (!timeout) {
|
||||
LNL_FLUSH_WORKQUEUE(xe->ordered_wq);
|
||||
err = do_compare(addr, args->value, args->mask,
|
||||
args->op);
|
||||
if (err <= 0) {
|
||||
drm_dbg(&xe->drm, "LNL_FLUSH_WORKQUEUE resolved ufence timeout\n");
|
||||
break;
|
||||
}
|
||||
err = -ETIME;
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user