drm fixes for 6.17-rc8 (or final)

fbcon:
 - fix OOB access in font allocation
 - fix integer overflow in font handling
 
 amdgpu:
 - Backlight fix
 - DC preblend fix
 - DCN 3.5 fix
 - Cleanup output_tf_change
 
 xe:
 - Don't expose sysfs attributes not applicable for VFs
 - Fix build with CONFIG_MODULES=n
 - Don't copy pinned kernel bos twice on suspend
 
 i915:
 - Set O_LARGEFILE in __create_shmem()
 - Guard reg_val against a INVALID_TRANSCODER [ddi]
 
 ast:
 - sleeps causing cpu stall fix
 
 panthor:
 - scheduler race condition fix
 
 gma500:
 - NULL ptr deref in hdmi teardown fix
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEEKbZHaGwW9KfbeusDHTzWXnEhr4FAmjWFIEACgkQDHTzWXnE
 hr60DQ//RMHlSkyfNdfVXeAmNxAp9ruzOS9mduDLoMYxgniSyB6o3vt5s3KYFP4B
 eusj2Lceg+9AU5J50iXUrhyQjFwE9gFWevjlEKlL5Rr5AxnHGrIvVQGD26C2PiT8
 JgMzKYNezYslpMLxyP0DuQxTzT6E88P1H7PUFF41KpoR1ZqcW2hGRSkKhSKv9aea
 OcqORMMTRtOy3m3mCKfSGUa1TmiPpxKAT6WQP9id3W8vIMHUElHy7K9Qx1tbycp/
 wlT7J66yN8xsVh5Z/8SUTRQXJJ05iBxm37zWvAiUD7DN+RrDgQDVNk65G9Gb3lMC
 FfuHARi79Ng2fUl/O99pqsEiOjgqtVcx0gL3pPtahnly8efS5huNu8s8IAcbepRv
 uBjrppewxLSM0YdJu5Dw2QSP9YsGsM7IF9bMk/362JndoVWp+T8zY1+snFqD4RRv
 P4LHpfmaf2uqtxeort8oiYKrXjNHBbcxsfnH/jWLMtgx2gW6Et8JruaOtesrNJ2G
 NVa02RWMsDMGaazrg2+4aH+NjjxxgrR1blZKttupsLtyYqftmW9l0OQ6zfg36/d5
 njoEUzgHrYBBHbRM3IR4OhQ5f54lWnBl2+MoeR6c1dI9A7QVFUUKjcwFA/TxI2tr
 kNZNoEI/rMOLo6b4yYBh+0l76XEyrxQIy9iAGZrog+pEECEs9GQ=
 =iIm3
 -----END PGP SIGNATURE-----

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

Pull drm fixes from Dave Airlie:
 "Weekly fixes, some fbcon font handling fixes, then amdgpu/xe/i915 with
  a few, and a few misc fixes for other drivers. Seems about right for
  this stage, and I don't know of anything outstanding.

  fbcon:
   - fix OOB access in font allocation
   - fix integer overflow in font handling

  amdgpu:
   - Backlight fix
   - DC preblend fix
   - DCN 3.5 fix
   - Cleanup output_tf_change

  xe:
   - Don't expose sysfs attributes not applicable for VFs
   - Fix build with CONFIG_MODULES=n
   - Don't copy pinned kernel bos twice on suspend

  i915:
   - Set O_LARGEFILE in __create_shmem()
   - Guard reg_val against a INVALID_TRANSCODER [ddi]

  ast:
   - sleeps causing cpu stall fix

  panthor:
   - scheduler race condition fix

  gma500:
   - NULL ptr deref in hdmi teardown fix"

* tag 'drm-fixes-2025-09-26' of https://gitlab.freedesktop.org/drm/kernel:
  drm/panthor: Defer scheduler entitiy destruction to queue release
  drm/amd/display: remove output_tf_change flag
  drm/amd/display: Init DCN35 clocks from pre-os HW values
  drm/amd/display: Use mpc.preblend flag to indicate preblend
  drm/amd/display: Only restore backlight after amdgpu_dm_init or dm_resume
  fbcon: Fix OOB access in font allocation
  drm/i915/ddi: Guard reg_val against a INVALID_TRANSCODER
  drm/i915: set O_LARGEFILE in __create_shmem()
  drm/xe: Don't copy pinned kernel bos twice on suspend
  drm/xe: Fix build with CONFIG_MODULES=n
  drm/xe/vf: Don't expose sysfs attributes not applicable for VFs
  fbcon: fix integer overflow in fbcon_do_set_font
  drm/gma500: Fix null dereference in hdmi teardown
  drm/ast: Use msleep instead of mdelay for edid read
This commit is contained in:
Linus Torvalds 2025-09-26 09:42:57 -07:00
commit 3170244bc5
17 changed files with 167 additions and 35 deletions

View File

@ -2037,6 +2037,8 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
dc_hardware_init(adev->dm.dc);
adev->dm.restore_backlight = true;
adev->dm.hpd_rx_offload_wq = hpd_rx_irq_create_workqueue(adev);
if (!adev->dm.hpd_rx_offload_wq) {
drm_err(adev_to_drm(adev), "failed to create hpd rx offload workqueue.\n");
@ -3399,6 +3401,7 @@ static int dm_resume(struct amdgpu_ip_block *ip_block)
dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D0);
dc_resume(dm->dc);
adev->dm.restore_backlight = true;
amdgpu_dm_irq_resume_early(adev);
@ -9829,7 +9832,6 @@ 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) {
@ -9949,7 +9951,6 @@ 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",
@ -10006,13 +10007,16 @@ static void amdgpu_dm_commit_streams(struct drm_atomic_state *state,
* 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
* So we set the backlight level with dm->brightness value after initial
* set mode. Use restore_backlight flag to avoid setting backlight level
* for every subsequent mode set.
*/
if (set_backlight_level) {
if (dm->restore_backlight) {
for (i = 0; i < dm->num_of_edps; i++) {
if (dm->backlight_dev[i])
amdgpu_dm_backlight_set_level(dm, i, dm->brightness[i]);
}
dm->restore_backlight = false;
}
}

View File

@ -610,6 +610,13 @@ struct amdgpu_display_manager {
*/
u32 actual_brightness[AMDGPU_DM_MAX_NUM_EDP];
/**
* @restore_backlight:
*
* Flag to indicate whether to restore backlight after modeset.
*/
bool restore_backlight;
/**
* @aux_hpd_discon_quirk:
*

View File

@ -821,7 +821,7 @@ int amdgpu_dm_verify_lut3d_size(struct amdgpu_device *adev,
struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state);
const struct drm_color_lut *shaper = NULL, *lut3d = NULL;
uint32_t exp_size, size, dim_size = MAX_COLOR_3DLUT_SIZE;
bool has_3dlut = adev->dm.dc->caps.color.dpp.hw_3d_lut;
bool has_3dlut = adev->dm.dc->caps.color.dpp.hw_3d_lut || adev->dm.dc->caps.color.mpc.preblend;
/* shaper LUT is only available if 3D LUT color caps */
exp_size = has_3dlut ? MAX_COLOR_LUT_ENTRIES : 0;

View File

@ -1633,7 +1633,7 @@ dm_atomic_plane_attach_color_mgmt_properties(struct amdgpu_display_manager *dm,
drm_object_attach_property(&plane->base,
dm->adev->mode_info.plane_ctm_property, 0);
if (dpp_color_caps.hw_3d_lut) {
if (dpp_color_caps.hw_3d_lut || dm->dc->caps.color.mpc.preblend) {
drm_object_attach_property(&plane->base,
mode_info.plane_shaper_lut_property, 0);
drm_object_attach_property(&plane->base,

View File

@ -587,9 +587,118 @@ bool dcn35_are_clock_states_equal(struct dc_clocks *a,
return true;
}
static void dcn35_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
static void dcn35_save_clk_registers_internal(struct dcn35_clk_internal *internal, struct clk_mgr *clk_mgr_base)
{
struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
// read dtbclk
internal->CLK1_CLK4_CURRENT_CNT = REG_READ(CLK1_CLK4_CURRENT_CNT);
internal->CLK1_CLK4_BYPASS_CNTL = REG_READ(CLK1_CLK4_BYPASS_CNTL);
// read dcfclk
internal->CLK1_CLK3_CURRENT_CNT = REG_READ(CLK1_CLK3_CURRENT_CNT);
internal->CLK1_CLK3_BYPASS_CNTL = REG_READ(CLK1_CLK3_BYPASS_CNTL);
// read dcf deep sleep divider
internal->CLK1_CLK3_DS_CNTL = REG_READ(CLK1_CLK3_DS_CNTL);
internal->CLK1_CLK3_ALLOW_DS = REG_READ(CLK1_CLK3_ALLOW_DS);
// read dppclk
internal->CLK1_CLK1_CURRENT_CNT = REG_READ(CLK1_CLK1_CURRENT_CNT);
internal->CLK1_CLK1_BYPASS_CNTL = REG_READ(CLK1_CLK1_BYPASS_CNTL);
// read dprefclk
internal->CLK1_CLK2_CURRENT_CNT = REG_READ(CLK1_CLK2_CURRENT_CNT);
internal->CLK1_CLK2_BYPASS_CNTL = REG_READ(CLK1_CLK2_BYPASS_CNTL);
// read dispclk
internal->CLK1_CLK0_CURRENT_CNT = REG_READ(CLK1_CLK0_CURRENT_CNT);
internal->CLK1_CLK0_BYPASS_CNTL = REG_READ(CLK1_CLK0_BYPASS_CNTL);
}
static void dcn35_save_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
struct clk_mgr_dcn35 *clk_mgr)
{
struct dcn35_clk_internal internal = {0};
char *bypass_clks[5] = {"0x0 DFS", "0x1 REFCLK", "0x2 ERROR", "0x3 400 FCH", "0x4 600 FCH"};
dcn35_save_clk_registers_internal(&internal, &clk_mgr->base.base);
regs_and_bypass->dcfclk = internal.CLK1_CLK3_CURRENT_CNT / 10;
regs_and_bypass->dcf_deep_sleep_divider = internal.CLK1_CLK3_DS_CNTL / 10;
regs_and_bypass->dcf_deep_sleep_allow = internal.CLK1_CLK3_ALLOW_DS;
regs_and_bypass->dprefclk = internal.CLK1_CLK2_CURRENT_CNT / 10;
regs_and_bypass->dispclk = internal.CLK1_CLK0_CURRENT_CNT / 10;
regs_and_bypass->dppclk = internal.CLK1_CLK1_CURRENT_CNT / 10;
regs_and_bypass->dtbclk = internal.CLK1_CLK4_CURRENT_CNT / 10;
regs_and_bypass->dppclk_bypass = internal.CLK1_CLK1_BYPASS_CNTL & 0x0007;
if (regs_and_bypass->dppclk_bypass < 0 || regs_and_bypass->dppclk_bypass > 4)
regs_and_bypass->dppclk_bypass = 0;
regs_and_bypass->dcfclk_bypass = internal.CLK1_CLK3_BYPASS_CNTL & 0x0007;
if (regs_and_bypass->dcfclk_bypass < 0 || regs_and_bypass->dcfclk_bypass > 4)
regs_and_bypass->dcfclk_bypass = 0;
regs_and_bypass->dispclk_bypass = internal.CLK1_CLK0_BYPASS_CNTL & 0x0007;
if (regs_and_bypass->dispclk_bypass < 0 || regs_and_bypass->dispclk_bypass > 4)
regs_and_bypass->dispclk_bypass = 0;
regs_and_bypass->dprefclk_bypass = internal.CLK1_CLK2_BYPASS_CNTL & 0x0007;
if (regs_and_bypass->dprefclk_bypass < 0 || regs_and_bypass->dprefclk_bypass > 4)
regs_and_bypass->dprefclk_bypass = 0;
if (clk_mgr->base.base.ctx->dc->debug.pstate_enabled) {
DC_LOG_SMU("clk_type,clk_value,deepsleep_cntl,deepsleep_allow,bypass\n");
DC_LOG_SMU("dcfclk,%d,%d,%d,%s\n",
regs_and_bypass->dcfclk,
regs_and_bypass->dcf_deep_sleep_divider,
regs_and_bypass->dcf_deep_sleep_allow,
bypass_clks[(int) regs_and_bypass->dcfclk_bypass]);
DC_LOG_SMU("dprefclk,%d,N/A,N/A,%s\n",
regs_and_bypass->dprefclk,
bypass_clks[(int) regs_and_bypass->dprefclk_bypass]);
DC_LOG_SMU("dispclk,%d,N/A,N/A,%s\n",
regs_and_bypass->dispclk,
bypass_clks[(int) regs_and_bypass->dispclk_bypass]);
// REGISTER VALUES
DC_LOG_SMU("reg_name,value,clk_type");
DC_LOG_SMU("CLK1_CLK3_CURRENT_CNT,%d,dcfclk",
internal.CLK1_CLK3_CURRENT_CNT);
DC_LOG_SMU("CLK1_CLK4_CURRENT_CNT,%d,dtbclk",
internal.CLK1_CLK4_CURRENT_CNT);
DC_LOG_SMU("CLK1_CLK3_DS_CNTL,%d,dcf_deep_sleep_divider",
internal.CLK1_CLK3_DS_CNTL);
DC_LOG_SMU("CLK1_CLK3_ALLOW_DS,%d,dcf_deep_sleep_allow",
internal.CLK1_CLK3_ALLOW_DS);
DC_LOG_SMU("CLK1_CLK2_CURRENT_CNT,%d,dprefclk",
internal.CLK1_CLK2_CURRENT_CNT);
DC_LOG_SMU("CLK1_CLK0_CURRENT_CNT,%d,dispclk",
internal.CLK1_CLK0_CURRENT_CNT);
DC_LOG_SMU("CLK1_CLK1_CURRENT_CNT,%d,dppclk",
internal.CLK1_CLK1_CURRENT_CNT);
DC_LOG_SMU("CLK1_CLK3_BYPASS_CNTL,%d,dcfclk_bypass",
internal.CLK1_CLK3_BYPASS_CNTL);
DC_LOG_SMU("CLK1_CLK2_BYPASS_CNTL,%d,dprefclk_bypass",
internal.CLK1_CLK2_BYPASS_CNTL);
DC_LOG_SMU("CLK1_CLK0_BYPASS_CNTL,%d,dispclk_bypass",
internal.CLK1_CLK0_BYPASS_CNTL);
DC_LOG_SMU("CLK1_CLK1_BYPASS_CNTL,%d,dppclk_bypass",
internal.CLK1_CLK1_BYPASS_CNTL);
}
}
static bool dcn35_is_spll_ssc_enabled(struct clk_mgr *clk_mgr_base)
@ -623,6 +732,7 @@ static void init_clk_states(struct clk_mgr *clk_mgr)
void dcn35_init_clocks(struct clk_mgr *clk_mgr)
{
struct clk_mgr_internal *clk_mgr_int = TO_CLK_MGR_INTERNAL(clk_mgr);
struct clk_mgr_dcn35 *clk_mgr_dcn35 = TO_CLK_MGR_DCN35(clk_mgr_int);
init_clk_states(clk_mgr);
@ -633,6 +743,13 @@ void dcn35_init_clocks(struct clk_mgr *clk_mgr)
else
clk_mgr->dp_dto_source_clock_in_khz = clk_mgr->dprefclk_khz;
dcn35_save_clk_registers(&clk_mgr->boot_snapshot, clk_mgr_dcn35);
clk_mgr->clks.ref_dtbclk_khz = clk_mgr->boot_snapshot.dtbclk * 10;
if (clk_mgr->boot_snapshot.dtbclk > 59000) {
/*dtbclk enabled based on */
clk_mgr->clks.dtbclk_en = true;
}
}
static struct clk_bw_params dcn35_bw_params = {
.vram_type = Ddr4MemType,
@ -1323,7 +1440,7 @@ void dcn35_clk_mgr_construct(
dcn35_bw_params.wm_table = ddr5_wm_table;
}
/* Saved clocks configured at boot for debug purposes */
dcn35_dump_clk_registers(&clk_mgr->base.base.boot_snapshot, clk_mgr);
dcn35_save_clk_registers(&clk_mgr->base.base.boot_snapshot, clk_mgr);
clk_mgr->base.base.dprefclk_khz = dcn35_smu_get_dprefclk(&clk_mgr->base);
clk_mgr->base.base.clks.ref_dtbclk_khz = 600000;

View File

@ -1348,7 +1348,6 @@ union surface_update_flags {
uint32_t in_transfer_func_change:1;
uint32_t input_csc_change:1;
uint32_t coeff_reduction_change:1;
uint32_t output_tf_change:1;
uint32_t pixel_format_change:1;
uint32_t plane_size_change:1;
uint32_t gamut_remap_change:1;

View File

@ -1982,10 +1982,8 @@ static void dcn20_program_pipe(
* updating on slave planes
*/
if (pipe_ctx->update_flags.bits.enable ||
pipe_ctx->update_flags.bits.plane_changed ||
pipe_ctx->stream->update_flags.bits.out_tf ||
(pipe_ctx->plane_state &&
pipe_ctx->plane_state->update_flags.bits.output_tf_change))
pipe_ctx->update_flags.bits.plane_changed ||
pipe_ctx->stream->update_flags.bits.out_tf)
hws->funcs.set_output_transfer_func(dc, pipe_ctx, pipe_ctx->stream);
/* If the pipe has been enabled or has a different opp, we

View File

@ -2019,10 +2019,8 @@ void dcn401_program_pipe(
* updating on slave planes
*/
if (pipe_ctx->update_flags.bits.enable ||
pipe_ctx->update_flags.bits.plane_changed ||
pipe_ctx->stream->update_flags.bits.out_tf ||
(pipe_ctx->plane_state &&
pipe_ctx->plane_state->update_flags.bits.output_tf_change))
pipe_ctx->update_flags.bits.plane_changed ||
pipe_ctx->stream->update_flags.bits.out_tf)
hws->funcs.set_output_transfer_func(dc, pipe_ctx, pipe_ctx->stream);
/* If the pipe has been enabled or has a different opp, we

View File

@ -134,7 +134,7 @@ static int ast_astdp_read_edid_block(void *data, u8 *buf, unsigned int block, si
* 3. The Delays are often longer a lot when system resume from S3/S4.
*/
if (j)
mdelay(j + 1);
msleep(j + 1);
/* Wait for EDID offset to show up in mirror register */
vgacrd7 = ast_get_index_reg(ast, AST_IO_VGACRI, 0xd7);

View File

@ -726,8 +726,8 @@ void oaktrail_hdmi_teardown(struct drm_device *dev)
if (hdmi_dev) {
pdev = hdmi_dev->dev;
pci_set_drvdata(pdev, NULL);
oaktrail_hdmi_i2c_exit(pdev);
pci_set_drvdata(pdev, NULL);
iounmap(hdmi_dev->regs);
kfree(hdmi_dev);
pci_dev_put(pdev);

View File

@ -596,8 +596,9 @@ intel_ddi_transcoder_func_reg_val_get(struct intel_encoder *encoder,
enum transcoder master;
master = crtc_state->mst_master_transcoder;
drm_WARN_ON(display->drm,
master == INVALID_TRANSCODER);
if (drm_WARN_ON(display->drm,
master == INVALID_TRANSCODER))
master = TRANSCODER_A;
temp |= TRANS_DDI_MST_TRANSPORT_SELECT(master);
}
} else {

View File

@ -514,6 +514,13 @@ static int __create_shmem(struct drm_i915_private *i915,
if (IS_ERR(filp))
return PTR_ERR(filp);
/*
* Prevent -EFBIG by allowing large writes beyond MAX_NON_LFS on shmem
* objects by setting O_LARGEFILE.
*/
if (force_o_largefile())
filp->f_flags |= O_LARGEFILE;
obj->filp = filp;
return 0;
}

View File

@ -886,8 +886,7 @@ static void group_free_queue(struct panthor_group *group, struct panthor_queue *
if (IS_ERR_OR_NULL(queue))
return;
if (queue->entity.fence_context)
drm_sched_entity_destroy(&queue->entity);
drm_sched_entity_destroy(&queue->entity);
if (queue->scheduler.ops)
drm_sched_fini(&queue->scheduler);
@ -3558,11 +3557,6 @@ int panthor_group_destroy(struct panthor_file *pfile, u32 group_handle)
if (!group)
return -EINVAL;
for (u32 i = 0; i < group->queue_count; i++) {
if (group->queues[i])
drm_sched_entity_destroy(&group->queues[i]->entity);
}
mutex_lock(&sched->reset.lock);
mutex_lock(&sched->lock);
group->destroyed = true;

View File

@ -158,8 +158,8 @@ int xe_bo_evict_all(struct xe_device *xe)
if (ret)
return ret;
ret = xe_bo_apply_to_pinned(xe, &xe->pinned.late.kernel_bo_present,
&xe->pinned.late.evicted, xe_bo_evict_pinned);
ret = xe_bo_apply_to_pinned(xe, &xe->pinned.late.external,
&xe->pinned.late.external, xe_bo_evict_pinned);
if (!ret)
ret = xe_bo_apply_to_pinned(xe, &xe->pinned.late.kernel_bo_present,

View File

@ -404,7 +404,7 @@ int __init xe_configfs_init(void)
return 0;
}
void __exit xe_configfs_exit(void)
void xe_configfs_exit(void)
{
configfs_unregister_subsystem(&xe_configfs);
}

View File

@ -308,7 +308,7 @@ int xe_device_sysfs_init(struct xe_device *xe)
return ret;
}
if (xe->info.platform == XE_BATTLEMAGE) {
if (xe->info.platform == XE_BATTLEMAGE && !IS_SRIOV_VF(xe)) {
ret = sysfs_create_files(&dev->kobj, auto_link_downgrade_attrs);
if (ret)
goto cleanup;

View File

@ -2504,7 +2504,7 @@ static int fbcon_set_font(struct vc_data *vc, const struct console_font *font,
unsigned charcount = font->charcount;
int w = font->width;
int h = font->height;
int size;
int size, alloc_size;
int i, csum;
u8 *new_data, *data = font->data;
int pitch = PITCH(font->width);
@ -2531,9 +2531,16 @@ static int fbcon_set_font(struct vc_data *vc, const struct console_font *font,
if (fbcon_invalid_charcount(info, charcount))
return -EINVAL;
size = CALC_FONTSZ(h, pitch, charcount);
/* Check for integer overflow in font size calculation */
if (check_mul_overflow(h, pitch, &size) ||
check_mul_overflow(size, charcount, &size))
return -EINVAL;
new_data = kmalloc(FONT_EXTRA_WORDS * sizeof(int) + size, GFP_USER);
/* Check for overflow in allocation size calculation */
if (check_add_overflow(FONT_EXTRA_WORDS * sizeof(int), size, &alloc_size))
return -EINVAL;
new_data = kmalloc(alloc_size, GFP_USER);
if (!new_data)
return -ENOMEM;