drm fixes for 6.18-rc5

sched:
 - Fix deadlock
 
 amdgpu:
 - Reset fixes
 - Misc fixes
 - Panel scaling fixes
 - HDMI fix
 - S0ix fixes
 - Hibernation fix
 - Secure display fix
 - Suspend fix
 - MST fix
 
 amdkfd:
 - Process cleanup fix
 
 xe:
 - Fix missing  synchronization on unbind
 - Fix device shutdown when doing FLR
 - Fix user fence signaling order
 
 i915:
 - Avoid lock inversion when pinning to GGTT on CHV/BXT+VTD
 - Fix conversion between clock ticks and nanoseconds
 
 mediatek:
 - Disable AFBC support on Mediatek DRM driver
 - Add pm_runtime support for GCE power control
 
 imagination:
 - kconfig: Fix dependencies
 
 nouveau:
 - Set DMA mask earlier
 - Advertize correct modifiers for GB20x
 
 pixpaper:
 - kconfig: Fix dependencies
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEEKbZHaGwW9KfbeusDHTzWXnEhr4FAmkOahUACgkQDHTzWXnE
 hr4tfQ//YrAFWBzlB6u08gOKj4KuH02pT9WKT/rtG99SX2zB1PtH8Z5QpKVcrlgb
 3dx2IuMm2sFGX3q17BKkNwPKTBSEVY2ISPasidpPp7Q9wLylbuzhrdIDKpGWBw+p
 Zq36avNUyev1WCz91t01jR/K51vG2b83rq9ZUoG+wIJswfUDmIOlfvI/TXOp7in2
 801W5oMAWi+NMr8VZTTPLY0Yya5k2oMD484IO28y/UcZ37t8t8ehQp9EX8wQLL7E
 KPee9bngEHUcrs8thJgkUchLzXJbjnpfnOqYodkgs4s890YcvLBbJPjVPxqTymiZ
 BT+6NKU4YnAkufA8JPlSNM+JhSn2VzGrdkZRRnQXtVxSVlh9fUTXNJaWVSvSucod
 O1UgJnc+Y/qsSjQsfuxKzNdLiFEOp6u2MLe8cZR419YU+KmrjTmqu+07BQjPONN7
 +JYprDuZNbYWcWNUL12Mu1EumwfSJlIqtSoZSn9zZ59ZL/IQPjjx4dA5nmasTnmz
 lA8J5hHWeG+TOEthVYe4/an6QUvBt+Hpq+3nG4iYMYfLQg/U2aTzic2KlZP0v/A5
 s9g0hMawsXxAAnm4JGsFkBIQ92nIPpNksQDj6ynqVG3IkO9Uf/8zsVSuoxfjDycG
 5PYQ4ILGlqbPYt/bW6PsWIZIMfEHcOfegwNLB8yoPDZwmpm+4y4=
 =COpG
 -----END PGP SIGNATURE-----

Merge tag 'drm-fixes-2025-11-08' of https://gitlab.freedesktop.org/drm/kernel

Pull drm fixes from Dave Airlie:
 "Back from travel, thanks to Simona for handling things. regular fixes,
  seems about the right size, but spread out a bit.

  amdgpu has the usual range of fixes, xe has a few fixes, and nouveau
  has a couple of fixes, one for blackwell modifiers on 8/16 bit
  surfaces.

  Otherwise a few small fixes for mediatek, sched, imagination and
  pixpaper.

  sched:
   - Fix deadlock

  amdgpu:
   - Reset fixes
   - Misc fixes
   - Panel scaling fixes
   - HDMI fix
   - S0ix fixes
   - Hibernation fix
   - Secure display fix
   - Suspend fix
   - MST fix

  amdkfd:
   - Process cleanup fix

  xe:
   - Fix missing  synchronization on unbind
   - Fix device shutdown when doing FLR
   - Fix user fence signaling order

  i915:
   - Avoid lock inversion when pinning to GGTT on CHV/BXT+VTD
   - Fix conversion between clock ticks and nanoseconds

  mediatek:
   - Disable AFBC support on Mediatek DRM driver
   - Add pm_runtime support for GCE power control

  imagination:
   - kconfig: Fix dependencies

  nouveau:
   - Set DMA mask earlier
   - Advertize correct modifiers for GB20x

  pixpaper:
   - kconfig: Fix dependencies"

* tag 'drm-fixes-2025-11-08' of https://gitlab.freedesktop.org/drm/kernel: (26 commits)
  drm/xe: Enforce correct user fence signaling order using
  drm/xe: Do clean shutdown also when using flr
  drm/xe: Move declarations under conditional branch
  drm/xe/guc: Synchronize Dead CT worker with unbind
  drm/amd/display: Enable mst when it's detected but yet to be initialized
  drm/amdgpu: Fix wait after reset sequence in S3
  drm/amd: Fix suspend failure with secure display TA
  drm/amdgpu: fix gpu page fault after hibernation on PF passthrough
  drm/tiny: pixpaper: add explicit dependency on MMU
  drm/nouveau: Advertise correct modifiers on GB20x
  drm: define NVIDIA DRM format modifiers for GB20x
  drm/nouveau: set DMA mask before creating the flush page
  drm/sched: Fix deadlock in drm_sched_entity_kill_jobs_cb
  drm/amd/display: Fix NULL deref in debugfs odm_combine_segments
  drm/amdkfd: Don't clear PT after process killed
  drm/amdgpu/smu: Handle S0ix for vangogh
  drm/amdgpu: Drop PMFW RLC notifier from amdgpu_device_suspend()
  drm/amd/display: Fix black screen with HDMI outputs
  drm/amd/display: Don't stretch non-native images by default in eDP
  drm/amd/pm: fix missing device_attr cleanup in amdgpu_pm_sysfs_init()
  ...
This commit is contained in:
Linus Torvalds 2025-11-07 14:51:11 -08:00
commit e811c33b1f
42 changed files with 311 additions and 125 deletions

View File

@ -1267,6 +1267,10 @@ static int unmap_bo_from_gpuvm(struct kgd_mem *mem,
(void)amdgpu_vm_bo_unmap(adev, bo_va, entry->va);
/* VM entity stopped if process killed, don't clear freed pt bo */
if (!amdgpu_vm_ready(vm))
return 0;
(void)amdgpu_vm_clear_freed(adev, vm, &bo_va->last_pt_update);
(void)amdgpu_sync_fence(sync, bo_va->last_pt_update, GFP_KERNEL);

View File

@ -5243,10 +5243,6 @@ int amdgpu_device_suspend(struct drm_device *dev, bool notify_clients)
if (amdgpu_sriov_vf(adev))
amdgpu_virt_release_full_gpu(adev, false);
r = amdgpu_dpm_notify_rlc_state(adev, false);
if (r)
return r;
return 0;
}

View File

@ -2632,9 +2632,14 @@ static int amdgpu_pmops_suspend_noirq(struct device *dev)
{
struct drm_device *drm_dev = dev_get_drvdata(dev);
struct amdgpu_device *adev = drm_to_adev(drm_dev);
int r;
if (amdgpu_acpi_should_gpu_reset(adev))
return amdgpu_asic_reset(adev);
if (amdgpu_acpi_should_gpu_reset(adev)) {
amdgpu_device_lock_reset_domain(adev->reset_domain);
r = amdgpu_asic_reset(adev);
amdgpu_device_unlock_reset_domain(adev->reset_domain);
return r;
}
return 0;
}

View File

@ -2355,8 +2355,11 @@ static int psp_securedisplay_initialize(struct psp_context *psp)
if (!ret && !psp->securedisplay_context.context.resp_status) {
psp->securedisplay_context.context.initialized = true;
mutex_init(&psp->securedisplay_context.mutex);
} else
} else {
/* don't try again */
psp->securedisplay_context.context.bin_desc.size_bytes = 0;
return ret;
}
mutex_lock(&psp->securedisplay_context.mutex);

View File

@ -407,7 +407,8 @@ static int aqua_vanjaram_switch_partition_mode(struct amdgpu_xcp_mgr *xcp_mgr,
return -EINVAL;
}
if (adev->kfd.init_complete && !amdgpu_in_reset(adev))
if (adev->kfd.init_complete && !amdgpu_in_reset(adev) &&
!adev->in_suspend)
flags |= AMDGPU_XCP_OPS_KFD;
if (flags & AMDGPU_XCP_OPS_KFD) {

View File

@ -3102,6 +3102,11 @@ static int gfx_v6_0_sw_init(struct amdgpu_ip_block *ip_block)
return r;
}
adev->gfx.gfx_supported_reset =
amdgpu_get_soft_full_reset_mask(&adev->gfx.gfx_ring[0]);
adev->gfx.compute_supported_reset =
amdgpu_get_soft_full_reset_mask(&adev->gfx.compute_ring[0]);
return r;
}

View File

@ -4399,6 +4399,11 @@ static int gfx_v7_0_sw_init(struct amdgpu_ip_block *ip_block)
gfx_v7_0_gpu_early_init(adev);
adev->gfx.gfx_supported_reset =
amdgpu_get_soft_full_reset_mask(&adev->gfx.gfx_ring[0]);
adev->gfx.compute_supported_reset =
amdgpu_get_soft_full_reset_mask(&adev->gfx.compute_ring[0]);
return r;
}

View File

@ -2023,6 +2023,11 @@ static int gfx_v8_0_sw_init(struct amdgpu_ip_block *ip_block)
if (r)
return r;
adev->gfx.gfx_supported_reset =
amdgpu_get_soft_full_reset_mask(&adev->gfx.gfx_ring[0]);
adev->gfx.compute_supported_reset =
amdgpu_get_soft_full_reset_mask(&adev->gfx.compute_ring[0]);
return 0;
}

View File

@ -2292,7 +2292,9 @@ static int gfx_v9_4_3_cp_resume(struct amdgpu_device *adev)
r = amdgpu_xcp_init(adev->xcp_mgr, num_xcp, mode);
} else {
if (amdgpu_xcp_query_partition_mode(adev->xcp_mgr,
if (adev->in_suspend)
amdgpu_xcp_restore_partition_mode(adev->xcp_mgr);
else if (amdgpu_xcp_query_partition_mode(adev->xcp_mgr,
AMDGPU_XCP_FL_NONE) ==
AMDGPU_UNKNOWN_COMPUTE_PARTITION_MODE)
r = amdgpu_xcp_switch_partition_mode(

View File

@ -142,13 +142,37 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
return err;
}
static int psp_v11_wait_for_tos_unload(struct psp_context *psp)
{
struct amdgpu_device *adev = psp->adev;
uint32_t sol_reg1, sol_reg2;
int retry_loop;
/* Wait for the TOS to be unloaded */
for (retry_loop = 0; retry_loop < 20; retry_loop++) {
sol_reg1 = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_81);
usleep_range(1000, 2000);
sol_reg2 = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_81);
if (sol_reg1 == sol_reg2)
return 0;
}
dev_err(adev->dev, "TOS unload failed, C2PMSG_33: %x C2PMSG_81: %x",
RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_33),
RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_81));
return -ETIME;
}
static int psp_v11_0_wait_for_bootloader(struct psp_context *psp)
{
struct amdgpu_device *adev = psp->adev;
int ret;
int retry_loop;
/* For a reset done at the end of S3, only wait for TOS to be unloaded */
if (adev->in_s3 && !(adev->flags & AMD_IS_APU) && amdgpu_in_reset(adev))
return psp_v11_wait_for_tos_unload(psp);
for (retry_loop = 0; retry_loop < 20; retry_loop++) {
/* Wait for bootloader to signify that is
ready having bit 31 of C2PMSG_35 set to 1 */

View File

@ -3563,6 +3563,7 @@ static int dm_resume(struct amdgpu_ip_block *ip_block)
/* Do mst topology probing after resuming cached state*/
drm_connector_list_iter_begin(ddev, &iter);
drm_for_each_connector_iter(connector, &iter) {
bool init = false;
if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
continue;
@ -3572,6 +3573,13 @@ static int dm_resume(struct amdgpu_ip_block *ip_block)
aconnector->mst_root)
continue;
scoped_guard(mutex, &aconnector->mst_mgr.lock) {
init = !aconnector->mst_mgr.mst_primary;
}
if (init)
dm_helpers_dp_mst_start_top_mgr(aconnector->dc_link->ctx,
aconnector->dc_link, false);
else
drm_dp_mst_topology_queue_probe(&aconnector->mst_mgr);
}
drm_connector_list_iter_end(&iter);
@ -8030,7 +8038,7 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder,
"mode %dx%d@%dHz is not native, enabling scaling\n",
adjusted_mode->hdisplay, adjusted_mode->vdisplay,
drm_mode_vrefresh(adjusted_mode));
dm_new_connector_state->scaling = RMX_FULL;
dm_new_connector_state->scaling = RMX_ASPECT;
}
return 0;
}

View File

@ -1302,7 +1302,8 @@ static int odm_combine_segments_show(struct seq_file *m, void *unused)
if (connector->status != connector_status_connected)
return -ENODEV;
if (pipe_ctx != NULL && pipe_ctx->stream_res.tg->funcs->get_odm_combine_segments)
if (pipe_ctx && pipe_ctx->stream_res.tg &&
pipe_ctx->stream_res.tg->funcs->get_odm_combine_segments)
pipe_ctx->stream_res.tg->funcs->get_odm_combine_segments(pipe_ctx->stream_res.tg, &segments);
seq_printf(m, "%d\n", segments);

View File

@ -1141,6 +1141,7 @@ static bool detect_link_and_local_sink(struct dc_link *link,
!sink->edid_caps.edid_hdmi)
sink->sink_signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
else if (dc_is_dvi_signal(sink->sink_signal) &&
dc_is_dvi_signal(link->connector_signal) &&
aud_support->hdmi_audio_native &&
sink->edid_caps.edid_hdmi)
sink->sink_signal = SIGNAL_TYPE_HDMI_TYPE_A;

View File

@ -195,24 +195,6 @@ int amdgpu_dpm_set_mp1_state(struct amdgpu_device *adev,
return ret;
}
int amdgpu_dpm_notify_rlc_state(struct amdgpu_device *adev, bool en)
{
int ret = 0;
const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
if (pp_funcs && pp_funcs->notify_rlc_state) {
mutex_lock(&adev->pm.mutex);
ret = pp_funcs->notify_rlc_state(
adev->powerplay.pp_handle,
en);
mutex_unlock(&adev->pm.mutex);
}
return ret;
}
int amdgpu_dpm_is_baco_supported(struct amdgpu_device *adev)
{
const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;

View File

@ -4724,14 +4724,14 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
ret = devm_device_add_group(adev->dev,
&amdgpu_pm_policy_attr_group);
if (ret)
goto err_out0;
goto err_out1;
}
if (amdgpu_dpm_is_temp_metrics_supported(adev, SMU_TEMP_METRIC_GPUBOARD)) {
ret = devm_device_add_group(adev->dev,
&amdgpu_board_attr_group);
if (ret)
goto err_out0;
goto err_out1;
if (amdgpu_pm_get_sensor_generic(adev, AMDGPU_PP_SENSOR_MAXNODEPOWERLIMIT,
(void *)&tmp) != -EOPNOTSUPP) {
sysfs_add_file_to_group(&adev->dev->kobj,

View File

@ -424,8 +424,6 @@ int amdgpu_dpm_mode1_reset(struct amdgpu_device *adev);
int amdgpu_dpm_set_mp1_state(struct amdgpu_device *adev,
enum pp_mp1_state mp1_state);
int amdgpu_dpm_notify_rlc_state(struct amdgpu_device *adev, bool en);
int amdgpu_dpm_set_gfx_power_up_by_imu(struct amdgpu_device *adev);
int amdgpu_dpm_baco_exit(struct amdgpu_device *adev);

View File

@ -2040,6 +2040,12 @@ static int smu_disable_dpms(struct smu_context *smu)
smu->is_apu && (amdgpu_in_reset(adev) || adev->in_s0ix))
return 0;
/* vangogh s0ix */
if ((amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(11, 5, 0) ||
amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(11, 5, 2)) &&
adev->in_s0ix)
return 0;
/*
* For gpu reset, runpm and hibernation through BACO,
* BACO feature has to be kept enabled.

View File

@ -2217,6 +2217,9 @@ static int vangogh_post_smu_init(struct smu_context *smu)
uint32_t total_cu = adev->gfx.config.max_cu_per_sh *
adev->gfx.config.max_sh_per_se * adev->gfx.config.max_shader_engines;
if (adev->in_s0ix)
return 0;
/* allow message will be sent after enable message on Vangogh*/
if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT) &&
(adev->pg_flags & AMD_PG_SUPPORT_GFX_PG)) {

View File

@ -205,7 +205,7 @@ static u64 div_u64_roundup(u64 nom, u32 den)
u64 intel_gt_clock_interval_to_ns(const struct intel_gt *gt, u64 count)
{
return div_u64_roundup(count * NSEC_PER_SEC, gt->clock_frequency);
return mul_u64_u32_div(count, NSEC_PER_SEC, gt->clock_frequency);
}
u64 intel_gt_pm_interval_to_ns(const struct intel_gt *gt, u64 count)
@ -215,7 +215,7 @@ u64 intel_gt_pm_interval_to_ns(const struct intel_gt *gt, u64 count)
u64 intel_gt_ns_to_clock_interval(const struct intel_gt *gt, u64 ns)
{
return div_u64_roundup(gt->clock_frequency * ns, NSEC_PER_SEC);
return mul_u64_u32_div(ns, gt->clock_frequency, NSEC_PER_SEC);
}
u64 intel_gt_ns_to_pm_interval(const struct intel_gt *gt, u64 ns)

View File

@ -1595,8 +1595,20 @@ int i915_vma_pin_ww(struct i915_vma *vma, struct i915_gem_ww_ctx *ww,
err_vma_res:
i915_vma_resource_free(vma_res);
err_fence:
if (work)
if (work) {
/*
* When pinning VMA to GGTT on CHV or BXT with VTD enabled,
* commit VMA binding asynchronously to avoid risk of lock
* inversion among reservation_ww locks held here and
* cpu_hotplug_lock acquired from stop_machine(), which we
* wrap around GGTT updates when running in those environments.
*/
if (i915_vma_is_ggtt(vma) &&
intel_vm_no_concurrent_access_wa(vma->vm->i915))
dma_fence_work_commit(&work->base);
else
dma_fence_work_commit_imm(&work->base);
}
err_rpm:
intel_runtime_pm_put(&vma->vm->i915->runtime_pm, wakeref);

View File

@ -7,6 +7,7 @@ config DRM_POWERVR
depends on DRM
depends on MMU
depends on PM
depends on POWER_SEQUENCING || !POWER_SEQUENCING
select DRM_EXEC
select DRM_GEM_SHMEM_HELPER
select DRM_SCHED

View File

@ -283,6 +283,10 @@ static void ddp_cmdq_cb(struct mbox_client *cl, void *mssg)
unsigned int i;
unsigned long flags;
/* release GCE HW usage and start autosuspend */
pm_runtime_mark_last_busy(cmdq_cl->chan->mbox->dev);
pm_runtime_put_autosuspend(cmdq_cl->chan->mbox->dev);
if (data->sta < 0)
return;
@ -618,6 +622,9 @@ static void mtk_crtc_update_config(struct mtk_crtc *mtk_crtc, bool needs_vblank)
mtk_crtc->config_updating = false;
spin_unlock_irqrestore(&mtk_crtc->config_lock, flags);
if (pm_runtime_resume_and_get(mtk_crtc->cmdq_client.chan->mbox->dev) < 0)
goto update_config_out;
mbox_send_message(mtk_crtc->cmdq_client.chan, cmdq_handle);
mbox_client_txdone(mtk_crtc->cmdq_client.chan, 0);
goto update_config_out;

View File

@ -21,9 +21,6 @@
static const u64 modifiers[] = {
DRM_FORMAT_MOD_LINEAR,
DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
AFBC_FORMAT_MOD_SPLIT |
AFBC_FORMAT_MOD_SPARSE),
DRM_FORMAT_MOD_INVALID,
};
@ -71,26 +68,7 @@ static bool mtk_plane_format_mod_supported(struct drm_plane *plane,
uint32_t format,
uint64_t modifier)
{
if (modifier == DRM_FORMAT_MOD_LINEAR)
return true;
if (modifier != DRM_FORMAT_MOD_ARM_AFBC(
AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
AFBC_FORMAT_MOD_SPLIT |
AFBC_FORMAT_MOD_SPARSE))
return false;
if (format != DRM_FORMAT_XRGB8888 &&
format != DRM_FORMAT_ARGB8888 &&
format != DRM_FORMAT_BGRX8888 &&
format != DRM_FORMAT_BGRA8888 &&
format != DRM_FORMAT_ABGR8888 &&
format != DRM_FORMAT_XBGR8888 &&
format != DRM_FORMAT_RGB888 &&
format != DRM_FORMAT_BGR888)
return false;
return true;
return modifier == DRM_FORMAT_MOD_LINEAR;
}
static void mtk_plane_destroy_state(struct drm_plane *plane,

View File

@ -2867,7 +2867,9 @@ nv50_display_create(struct drm_device *dev)
}
/* Assign the correct format modifiers */
if (disp->disp->object.oclass >= TU102_DISP)
if (disp->disp->object.oclass >= GB202_DISP)
nouveau_display(dev)->format_modifiers = wndwca7e_modifiers;
else if (disp->disp->object.oclass >= TU102_DISP)
nouveau_display(dev)->format_modifiers = wndwc57e_modifiers;
else
if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_FERMI)

View File

@ -104,4 +104,5 @@ struct nouveau_encoder *nv50_real_outp(struct drm_encoder *encoder);
extern const u64 disp50xx_modifiers[];
extern const u64 disp90xx_modifiers[];
extern const u64 wndwc57e_modifiers[];
extern const u64 wndwca7e_modifiers[];
#endif

View File

@ -786,13 +786,14 @@ nv50_wndw_destroy(struct drm_plane *plane)
}
/* This function assumes the format has already been validated against the plane
* and the modifier was validated against the device-wides modifier list at FB
* and the modifier was validated against the device-wide modifier list at FB
* creation time.
*/
static bool nv50_plane_format_mod_supported(struct drm_plane *plane,
u32 format, u64 modifier)
{
struct nouveau_drm *drm = nouveau_drm(plane->dev);
const struct drm_format_info *info = drm_format_info(format);
uint8_t i;
/* All chipsets can display all formats in linear layout */
@ -800,13 +801,32 @@ static bool nv50_plane_format_mod_supported(struct drm_plane *plane,
return true;
if (drm->client.device.info.chipset < 0xc0) {
const struct drm_format_info *info = drm_format_info(format);
const uint8_t kind = (modifier >> 12) & 0xff;
if (!format) return false;
for (i = 0; i < info->num_planes; i++)
if ((info->cpp[i] != 4) && kind != 0x70) return false;
} else if (drm->client.device.info.chipset >= 0x1b2) {
const uint8_t slayout = ((modifier >> 22) & 0x1) |
((modifier >> 25) & 0x6);
if (!format)
return false;
/*
* Note in practice this implies only formats where cpp is equal
* for each plane, or >= 4 for all planes, are supported.
*/
for (i = 0; i < info->num_planes; i++) {
if (((info->cpp[i] == 2) && slayout != 3) ||
((info->cpp[i] == 1) && slayout != 2) ||
((info->cpp[i] >= 4) && slayout != 1))
return false;
/* 24-bit not supported. It has yet another layout */
WARN_ON(info->cpp[i] == 3);
}
}
return true;

View File

@ -179,6 +179,39 @@ wndwca7e_ntfy_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
return 0;
}
/****************************************************************
* Log2(block height) ----------------------------+ *
* Page Kind ----------------------------------+ | *
* Gob Height/Page Kind Generation ------+ | | *
* Sector layout -------+ | | | *
* Compression ------+ | | | | */
const u64 wndwca7e_modifiers[] = { /* | | | | | */
/* 4cpp+ modifiers */
DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 1, 2, 0x06, 0),
DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 1, 2, 0x06, 1),
DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 1, 2, 0x06, 2),
DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 1, 2, 0x06, 3),
DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 1, 2, 0x06, 4),
DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 1, 2, 0x06, 5),
/* 1cpp/8bpp modifiers */
DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 2, 2, 0x06, 0),
DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 2, 2, 0x06, 1),
DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 2, 2, 0x06, 2),
DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 2, 2, 0x06, 3),
DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 2, 2, 0x06, 4),
DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 2, 2, 0x06, 5),
/* 2cpp/16bpp modifiers */
DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 3, 2, 0x06, 0),
DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 3, 2, 0x06, 1),
DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 3, 2, 0x06, 2),
DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 3, 2, 0x06, 3),
DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 3, 2, 0x06, 4),
DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 3, 2, 0x06, 5),
/* All formats support linear */
DRM_FORMAT_MOD_LINEAR,
DRM_FORMAT_MOD_INVALID
};
static const struct nv50_wndw_func
wndwca7e = {
.acquire = wndwc37e_acquire,

View File

@ -1695,6 +1695,18 @@ nvkm_device_pci_new(struct pci_dev *pci_dev, const char *cfg, const char *dbg,
*pdevice = &pdev->device;
pdev->pdev = pci_dev;
/* Set DMA mask based on capabilities reported by the MMU subdev. */
if (pdev->device.mmu && !pdev->device.pci->agp.bridge)
bits = pdev->device.mmu->dma_bits;
else
bits = 32;
ret = dma_set_mask_and_coherent(&pci_dev->dev, DMA_BIT_MASK(bits));
if (ret && bits != 32) {
dma_set_mask_and_coherent(&pci_dev->dev, DMA_BIT_MASK(32));
pdev->device.mmu->dma_bits = 32;
}
ret = nvkm_device_ctor(&nvkm_device_pci_func, quirk, &pci_dev->dev,
pci_is_pcie(pci_dev) ? NVKM_DEVICE_PCIE :
pci_find_capability(pci_dev, PCI_CAP_ID_AGP) ?
@ -1708,17 +1720,5 @@ nvkm_device_pci_new(struct pci_dev *pci_dev, const char *cfg, const char *dbg,
if (ret)
return ret;
/* Set DMA mask based on capabilities reported by the MMU subdev. */
if (pdev->device.mmu && !pdev->device.pci->agp.bridge)
bits = pdev->device.mmu->dma_bits;
else
bits = 32;
ret = dma_set_mask_and_coherent(&pci_dev->dev, DMA_BIT_MASK(bits));
if (ret && bits != 32) {
dma_set_mask_and_coherent(&pci_dev->dev, DMA_BIT_MASK(32));
pdev->device.mmu->dma_bits = 32;
}
return 0;
}

View File

@ -173,26 +173,15 @@ int drm_sched_entity_error(struct drm_sched_entity *entity)
}
EXPORT_SYMBOL(drm_sched_entity_error);
static void drm_sched_entity_kill_jobs_cb(struct dma_fence *f,
struct dma_fence_cb *cb);
static void drm_sched_entity_kill_jobs_work(struct work_struct *wrk)
{
struct drm_sched_job *job = container_of(wrk, typeof(*job), work);
drm_sched_fence_scheduled(job->s_fence, NULL);
drm_sched_fence_finished(job->s_fence, -ESRCH);
WARN_ON(job->s_fence->parent);
job->sched->ops->free_job(job);
}
/* Signal the scheduler finished fence when the entity in question is killed. */
static void drm_sched_entity_kill_jobs_cb(struct dma_fence *f,
struct dma_fence_cb *cb)
{
struct drm_sched_job *job = container_of(cb, struct drm_sched_job,
finish_cb);
struct dma_fence *f;
unsigned long index;
dma_fence_put(f);
/* Wait for all dependencies to avoid data corruptions */
xa_for_each(&job->dependencies, index, f) {
struct drm_sched_fence *s_fence = to_drm_sched_fence(f);
@ -220,6 +209,21 @@ static void drm_sched_entity_kill_jobs_cb(struct dma_fence *f,
dma_fence_put(f);
}
drm_sched_fence_scheduled(job->s_fence, NULL);
drm_sched_fence_finished(job->s_fence, -ESRCH);
WARN_ON(job->s_fence->parent);
job->sched->ops->free_job(job);
}
/* Signal the scheduler finished fence when the entity in question is killed. */
static void drm_sched_entity_kill_jobs_cb(struct dma_fence *f,
struct dma_fence_cb *cb)
{
struct drm_sched_job *job = container_of(cb, struct drm_sched_job,
finish_cb);
dma_fence_put(f);
INIT_WORK(&job->work, drm_sched_entity_kill_jobs_work);
schedule_work(&job->work);
}

View File

@ -85,6 +85,7 @@ config DRM_PANEL_MIPI_DBI
config DRM_PIXPAPER
tristate "DRM support for PIXPAPER display panels"
depends on DRM && SPI
depends on MMU
select DRM_CLIENT_SELECTION
select DRM_GEM_SHMEM_HELPER
select DRM_KMS_HELPER

View File

@ -988,7 +988,6 @@ void xe_device_shutdown(struct xe_device *xe)
drm_dbg(&xe->drm, "Shutting down device\n");
if (xe_driver_flr_disabled(xe)) {
xe_display_pm_shutdown(xe);
xe_irq_suspend(xe);
@ -997,7 +996,8 @@ void xe_device_shutdown(struct xe_device *xe)
xe_gt_shutdown(gt);
xe_display_pm_shutdown_late(xe);
} else {
if (!xe_driver_flr_disabled(xe)) {
/* BOOM! */
__xe_driver_flr(xe);
}

View File

@ -165,7 +165,8 @@ int xe_exec_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
for (num_syncs = 0; num_syncs < args->num_syncs; num_syncs++) {
err = xe_sync_entry_parse(xe, xef, &syncs[num_syncs],
&syncs_user[num_syncs], SYNC_PARSE_FLAG_EXEC |
&syncs_user[num_syncs], NULL, 0,
SYNC_PARSE_FLAG_EXEC |
(xe_vm_in_lr_mode(vm) ?
SYNC_PARSE_FLAG_LR_MODE : 0));
if (err)

View File

@ -10,6 +10,7 @@
#include <drm/drm_device.h>
#include <drm/drm_drv.h>
#include <drm/drm_file.h>
#include <drm/drm_syncobj.h>
#include <uapi/drm/xe_drm.h>
#include "xe_dep_scheduler.h"
@ -324,6 +325,16 @@ struct xe_exec_queue *xe_exec_queue_create_bind(struct xe_device *xe,
}
xe_vm_put(migrate_vm);
if (!IS_ERR(q)) {
int err = drm_syncobj_create(&q->ufence_syncobj,
DRM_SYNCOBJ_CREATE_SIGNALED,
NULL);
if (err) {
xe_exec_queue_put(q);
return ERR_PTR(err);
}
}
return q;
}
ALLOW_ERROR_INJECTION(xe_exec_queue_create_bind, ERRNO);
@ -333,6 +344,9 @@ void xe_exec_queue_destroy(struct kref *ref)
struct xe_exec_queue *q = container_of(ref, struct xe_exec_queue, refcount);
struct xe_exec_queue *eq, *next;
if (q->ufence_syncobj)
drm_syncobj_put(q->ufence_syncobj);
if (xe_exec_queue_uses_pxp(q))
xe_pxp_exec_queue_remove(gt_to_xe(q->gt)->pxp, q);

View File

@ -15,6 +15,7 @@
#include "xe_hw_fence_types.h"
#include "xe_lrc_types.h"
struct drm_syncobj;
struct xe_execlist_exec_queue;
struct xe_gt;
struct xe_guc_exec_queue;
@ -155,6 +156,12 @@ struct xe_exec_queue {
struct list_head link;
} pxp;
/** @ufence_syncobj: User fence syncobj */
struct drm_syncobj *ufence_syncobj;
/** @ufence_timeline_value: User fence timeline value */
u64 ufence_timeline_value;
/** @ops: submission backend exec queue operations */
const struct xe_exec_queue_ops *ops;

View File

@ -200,6 +200,9 @@ static void guc_ct_fini(struct drm_device *drm, void *arg)
{
struct xe_guc_ct *ct = arg;
#if IS_ENABLED(CONFIG_DRM_XE_DEBUG)
cancel_work_sync(&ct->dead.worker);
#endif
ct_exit_safe_mode(ct);
destroy_workqueue(ct->g2h_wq);
xa_destroy(&ct->fence_lookup);

View File

@ -10,6 +10,7 @@
#include <drm/drm_drv.h>
#include <drm/drm_managed.h>
#include <drm/drm_syncobj.h>
#include <uapi/drm/xe_drm.h>
#include <generated/xe_wa_oob.h>
@ -1389,7 +1390,9 @@ static int xe_oa_user_extensions(struct xe_oa *oa, enum xe_oa_user_extn_from fro
return 0;
}
static int xe_oa_parse_syncs(struct xe_oa *oa, struct xe_oa_open_param *param)
static int xe_oa_parse_syncs(struct xe_oa *oa,
struct xe_oa_stream *stream,
struct xe_oa_open_param *param)
{
int ret, num_syncs, num_ufence = 0;
@ -1409,7 +1412,9 @@ static int xe_oa_parse_syncs(struct xe_oa *oa, struct xe_oa_open_param *param)
for (num_syncs = 0; num_syncs < param->num_syncs; num_syncs++) {
ret = xe_sync_entry_parse(oa->xe, param->xef, &param->syncs[num_syncs],
&param->syncs_user[num_syncs], 0);
&param->syncs_user[num_syncs],
stream->ufence_syncobj,
++stream->ufence_timeline_value, 0);
if (ret)
goto err_syncs;
@ -1539,7 +1544,7 @@ static long xe_oa_config_locked(struct xe_oa_stream *stream, u64 arg)
return -ENODEV;
param.xef = stream->xef;
err = xe_oa_parse_syncs(stream->oa, &param);
err = xe_oa_parse_syncs(stream->oa, stream, &param);
if (err)
goto err_config_put;
@ -1635,6 +1640,7 @@ static void xe_oa_destroy_locked(struct xe_oa_stream *stream)
if (stream->exec_q)
xe_exec_queue_put(stream->exec_q);
drm_syncobj_put(stream->ufence_syncobj);
kfree(stream);
}
@ -1826,6 +1832,7 @@ static int xe_oa_stream_open_ioctl_locked(struct xe_oa *oa,
struct xe_oa_open_param *param)
{
struct xe_oa_stream *stream;
struct drm_syncobj *ufence_syncobj;
int stream_fd;
int ret;
@ -1836,17 +1843,31 @@ static int xe_oa_stream_open_ioctl_locked(struct xe_oa *oa,
goto exit;
}
ret = drm_syncobj_create(&ufence_syncobj, DRM_SYNCOBJ_CREATE_SIGNALED,
NULL);
if (ret)
goto exit;
stream = kzalloc(sizeof(*stream), GFP_KERNEL);
if (!stream) {
ret = -ENOMEM;
goto exit;
goto err_syncobj;
}
stream->ufence_syncobj = ufence_syncobj;
stream->oa = oa;
ret = xe_oa_stream_init(stream, param);
ret = xe_oa_parse_syncs(oa, stream, param);
if (ret)
goto err_free;
ret = xe_oa_stream_init(stream, param);
if (ret) {
while (param->num_syncs--)
xe_sync_entry_cleanup(&param->syncs[param->num_syncs]);
kfree(param->syncs);
goto err_free;
}
if (!param->disabled) {
ret = xe_oa_enable_locked(stream);
if (ret)
@ -1870,6 +1891,8 @@ static int xe_oa_stream_open_ioctl_locked(struct xe_oa *oa,
xe_oa_stream_destroy(stream);
err_free:
kfree(stream);
err_syncobj:
drm_syncobj_put(ufence_syncobj);
exit:
return ret;
}
@ -2083,22 +2106,14 @@ int xe_oa_stream_open_ioctl(struct drm_device *dev, u64 data, struct drm_file *f
goto err_exec_q;
}
ret = xe_oa_parse_syncs(oa, &param);
if (ret)
goto err_exec_q;
mutex_lock(&param.hwe->gt->oa.gt_lock);
ret = xe_oa_stream_open_ioctl_locked(oa, &param);
mutex_unlock(&param.hwe->gt->oa.gt_lock);
if (ret < 0)
goto err_sync_cleanup;
goto err_exec_q;
return ret;
err_sync_cleanup:
while (param.num_syncs--)
xe_sync_entry_cleanup(&param.syncs[param.num_syncs]);
kfree(param.syncs);
err_exec_q:
if (param.exec_q)
xe_exec_queue_put(param.exec_q);

View File

@ -15,6 +15,8 @@
#include "regs/xe_reg_defs.h"
#include "xe_hw_engine_types.h"
struct drm_syncobj;
#define DEFAULT_XE_OA_BUFFER_SIZE SZ_16M
enum xe_oa_report_header {
@ -248,6 +250,12 @@ struct xe_oa_stream {
/** @xef: xe_file with which the stream was opened */
struct xe_file *xef;
/** @ufence_syncobj: User fence syncobj */
struct drm_syncobj *ufence_syncobj;
/** @ufence_timeline_value: User fence timeline value */
u64 ufence_timeline_value;
/** @last_fence: fence to use in stream destroy when needed */
struct dma_fence *last_fence;

View File

@ -113,6 +113,8 @@ static void user_fence_cb(struct dma_fence *fence, struct dma_fence_cb *cb)
int xe_sync_entry_parse(struct xe_device *xe, struct xe_file *xef,
struct xe_sync_entry *sync,
struct drm_xe_sync __user *sync_user,
struct drm_syncobj *ufence_syncobj,
u64 ufence_timeline_value,
unsigned int flags)
{
struct drm_xe_sync sync_in;
@ -192,10 +194,15 @@ int xe_sync_entry_parse(struct xe_device *xe, struct xe_file *xef,
if (exec) {
sync->addr = sync_in.addr;
} else {
sync->ufence_timeline_value = ufence_timeline_value;
sync->ufence = user_fence_create(xe, sync_in.addr,
sync_in.timeline_value);
if (XE_IOCTL_DBG(xe, IS_ERR(sync->ufence)))
return PTR_ERR(sync->ufence);
sync->ufence_chain_fence = dma_fence_chain_alloc();
if (!sync->ufence_chain_fence)
return -ENOMEM;
sync->ufence_syncobj = ufence_syncobj;
}
break;
@ -239,7 +246,12 @@ void xe_sync_entry_signal(struct xe_sync_entry *sync, struct dma_fence *fence)
} else if (sync->ufence) {
int err;
dma_fence_get(fence);
drm_syncobj_add_point(sync->ufence_syncobj,
sync->ufence_chain_fence,
fence, sync->ufence_timeline_value);
sync->ufence_chain_fence = NULL;
fence = drm_syncobj_fence_get(sync->ufence_syncobj);
user_fence_get(sync->ufence);
err = dma_fence_add_callback(fence, &sync->ufence->cb,
user_fence_cb);
@ -259,7 +271,8 @@ void xe_sync_entry_cleanup(struct xe_sync_entry *sync)
drm_syncobj_put(sync->syncobj);
dma_fence_put(sync->fence);
dma_fence_chain_free(sync->chain_fence);
if (sync->ufence)
dma_fence_chain_free(sync->ufence_chain_fence);
if (!IS_ERR_OR_NULL(sync->ufence))
user_fence_put(sync->ufence);
}

View File

@ -8,6 +8,7 @@
#include "xe_sync_types.h"
struct drm_syncobj;
struct xe_device;
struct xe_exec_queue;
struct xe_file;
@ -21,6 +22,8 @@ struct xe_vm;
int xe_sync_entry_parse(struct xe_device *xe, struct xe_file *xef,
struct xe_sync_entry *sync,
struct drm_xe_sync __user *sync_user,
struct drm_syncobj *ufence_syncobj,
u64 ufence_timeline_value,
unsigned int flags);
int xe_sync_entry_add_deps(struct xe_sync_entry *sync,
struct xe_sched_job *job);

View File

@ -18,9 +18,12 @@ struct xe_sync_entry {
struct drm_syncobj *syncobj;
struct dma_fence *fence;
struct dma_fence_chain *chain_fence;
struct dma_fence_chain *ufence_chain_fence;
struct drm_syncobj *ufence_syncobj;
struct xe_user_fence *ufence;
u64 addr;
u64 timeline_value;
u64 ufence_timeline_value;
u32 type;
u32 flags;
};

View File

@ -3606,8 +3606,12 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
syncs_user = u64_to_user_ptr(args->syncs);
for (num_syncs = 0; num_syncs < args->num_syncs; num_syncs++) {
struct xe_exec_queue *__q = q ?: vm->q[0];
err = xe_sync_entry_parse(xe, xef, &syncs[num_syncs],
&syncs_user[num_syncs],
__q->ufence_syncobj,
++__q->ufence_timeline_value,
(xe_vm_in_lr_mode(vm) ?
SYNC_PARSE_FLAG_LR_MODE : 0) |
(!args->num_binds ?

View File

@ -979,14 +979,20 @@ extern "C" {
* 2 = Gob Height 8, Turing+ Page Kind mapping
* 3 = Reserved for future use.
*
* 22:22 s Sector layout. On Tegra GPUs prior to Xavier, there is a further
* bit remapping step that occurs at an even lower level than the
* page kind and block linear swizzles. This causes the layout of
* surfaces mapped in those SOC's GPUs to be incompatible with the
* equivalent mapping on other GPUs in the same system.
* 22:22 s Sector layout. There is a further bit remapping step that occurs
* 26:27 at an even lower level than the page kind and block linear
* swizzles. This causes the bit arrangement of surfaces in memory
* to differ subtly, and prevents direct sharing of surfaces between
* GPUs with different layouts.
*
* 0 = Tegra K1 - Tegra Parker/TX2 Layout.
* 1 = Desktop GPU and Tegra Xavier+ Layout
* 0 = Tegra K1 - Tegra Parker/TX2 Layout
* 1 = Pre-GB20x, GB20x 32+ bpp, GB10, Tegra Xavier-Orin Layout
* 2 = GB20x(Blackwell 2)+ 8 bpp surface layout
* 3 = GB20x(Blackwell 2)+ 16 bpp surface layout
* 4 = Reserved for future use.
* 5 = Reserved for future use.
* 6 = Reserved for future use.
* 7 = Reserved for future use.
*
* 25:23 c Lossless Framebuffer Compression type.
*
@ -1001,7 +1007,7 @@ extern "C" {
* 6 = Reserved for future use
* 7 = Reserved for future use
*
* 55:25 - Reserved for future use. Must be zero.
* 55:28 - Reserved for future use. Must be zero.
*/
#define DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(c, s, g, k, h) \
fourcc_mod_code(NVIDIA, (0x10 | \
@ -1009,6 +1015,7 @@ extern "C" {
(((k) & 0xff) << 12) | \
(((g) & 0x3) << 20) | \
(((s) & 0x1) << 22) | \
(((s) & 0x6) << 25) | \
(((c) & 0x7) << 23)))
/* To grandfather in prior block linear format modifiers to the above layout,