Pull drm fixes from Dave Airlie:
 "Probably a good thing you decided to do an rc8 in this round. Nothing
  stands out, but xe/amdgpu and mediatek all have a bunch of fixes, and
  then there are a few other single patches. Hopefully next week is
  calmer for release.

  xe:
   - Disallow bind-queue sharing across multiple VMs
   - Fix xe userptr in the absence of CONFIG_DEVICE_PRIVATE
   - Fix a missed page count update
   - Fix a confused argument to alloc_workqueue()
   - Kernel-doc fixes
   - Disable a workaround on VFs
   - Fix a job lock assert
   - Update wedged.mode only after successful reset policy change
   - Select CONFIG_DEVICE_PRIVATE when DRM_XE_GPUSVM is selected

  amdgpu:
   - fix color pipeline string leak
   - GC 12 fix
   - Misc error path fixes
   - DC analog fix
   - SMU 6 fixes
   - TLB flush fix
   - DC idle optimization fix

  amdkfd:
   - GC 11 cooperative launch fix

  imagination:
   - sync wait for logtype update completion to ensure FW trace
     is available

  bridge/synopsis:
   - Fix error paths in dw_dp_bind

  nouveau:
   - Add and implement missing DSB connector types, and improve
     unknown connector handling
   - Set missing atomic function ops

  intel:
   - place 3D lut at correct place in pipeline
   - fix color pipeline string leak

  vkms:
   - fix color pipeline string leak

  mediatek:
   - Fix platform_get_irq() error checking
   - HDMI DDC v2 driver fixes
   - dpi: Find next bridge during probe
   - mtk_gem: Partial refactor and use drm_gem_dma_object
   - dt-bindings: Fix typo 'hardwares' to 'hardware'"

* tag 'drm-fixes-2026-01-23' of https://gitlab.freedesktop.org/drm/kernel: (38 commits)
  Revert "drm/amd/display: pause the workload setting in dm"
  drm/xe: Select CONFIG_DEVICE_PRIVATE when DRM_XE_GPUSVM is selected
  drm, drm/xe: Fix xe userptr in the absence of CONFIG_DEVICE_PRIVATE
  drm/i915/display: Fix color pipeline enum name leak
  drm/vkms: Fix color pipeline enum name leak
  drm/amd/display: Fix color pipeline enum name leak
  drm/i915/color: Place 3D LUT after CSC in plane color pipeline
  drm/nouveau/disp: Set drm_mode_config_funcs.atomic_(check|commit)
  drm/nouveau: implement missing DCB connector types; gracefully handle unknown connectors
  drm/nouveau: add missing DCB connector types
  drm/amdgpu: fix type for wptr in ring backup
  drm/amdgpu: Fix validating flush_gpu_tlb_pasid()
  drm/amd/pm: Workaround SI powertune issue on Radeon 430 (v2)
  drm/amd/pm: Don't clear SI SMC table when setting power limit
  drm/amd/pm: Fix si_dpm mmCG_THERMAL_INT setting
  drm/xe: Update wedged.mode only after successful reset policy change
  drm/xe/migrate: fix job lock assert
  drm/xe/uapi: disallow bind queue sharing
  drm/amd/display: Only poll analog connectors
  drm/amdgpu: fix error handling in ib_schedule()
  ...
This commit is contained in:
Linus Torvalds
2026-01-23 09:01:26 -08:00
48 changed files with 561 additions and 405 deletions
@@ -11,7 +11,7 @@ maintainers:
- Jitao shi <jitao.shi@mediatek.com>
description: |
MediaTek DP and eDP are different hardwares and there are some features
MediaTek DP and eDP are different hardware and there are some features
which are not supported for eDP. For example, audio is not supported for
eDP. Therefore, we need to use two different compatibles to describe them.
In addition, We just need to enable the power domain of DP, so the clock
+1 -1
View File
@@ -210,7 +210,7 @@ config DRM_GPUVM
config DRM_GPUSVM
tristate
depends on DRM && DEVICE_PRIVATE
depends on DRM
select HMM_MIRROR
select MMU_NOTIFIER
help
+3 -1
View File
@@ -108,8 +108,10 @@ obj-$(CONFIG_DRM_EXEC) += drm_exec.o
obj-$(CONFIG_DRM_GPUVM) += drm_gpuvm.o
drm_gpusvm_helper-y := \
drm_gpusvm.o\
drm_gpusvm.o
drm_gpusvm_helper-$(CONFIG_ZONE_DEVICE) += \
drm_pagemap.o
obj-$(CONFIG_DRM_GPUSVM) += drm_gpusvm_helper.o
obj-$(CONFIG_DRM_BUDDY) += drm_buddy.o
+1 -1
View File
@@ -763,7 +763,7 @@ void amdgpu_fence_save_wptr(struct amdgpu_fence *af)
}
static void amdgpu_ring_backup_unprocessed_command(struct amdgpu_ring *ring,
u64 start_wptr, u32 end_wptr)
u64 start_wptr, u64 end_wptr)
{
unsigned int first_idx = start_wptr & ring->buf_mask;
unsigned int last_idx = end_wptr & ring->buf_mask;
+4 -2
View File
@@ -733,8 +733,10 @@ int amdgpu_gmc_flush_gpu_tlb_pasid(struct amdgpu_device *adev, uint16_t pasid,
if (!adev->gmc.flush_pasid_uses_kiq || !ring->sched.ready) {
if (!adev->gmc.gmc_funcs->flush_gpu_tlb_pasid)
return 0;
if (!adev->gmc.gmc_funcs->flush_gpu_tlb_pasid) {
r = 0;
goto error_unlock_reset;
}
if (adev->gmc.flush_tlb_needs_extra_type_2)
adev->gmc.gmc_funcs->flush_gpu_tlb_pasid(adev, pasid,
+1 -1
View File
@@ -302,7 +302,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
if (job && job->vmid)
amdgpu_vmid_reset(adev, ring->vm_hub, job->vmid);
amdgpu_ring_undo(ring);
return r;
goto free_fence;
}
*f = &af->base;
/* get a ref for the job */
+5 -2
View File
@@ -217,8 +217,11 @@ int amdgpu_job_alloc(struct amdgpu_device *adev, struct amdgpu_vm *vm,
if (!entity)
return 0;
return drm_sched_job_init(&(*job)->base, entity, 1, owner,
drm_client_id);
r = drm_sched_job_init(&(*job)->base, entity, 1, owner, drm_client_id);
if (!r)
return 0;
kfree((*job)->hw_vm_fence);
err_fence:
kfree((*job)->hw_fence);
-12
View File
@@ -278,7 +278,6 @@ static void gfx_v12_0_select_se_sh(struct amdgpu_device *adev, u32 se_num,
u32 sh_num, u32 instance, int xcc_id);
static u32 gfx_v12_0_get_wgp_active_bitmap_per_sh(struct amdgpu_device *adev);
static void gfx_v12_0_ring_emit_frame_cntl(struct amdgpu_ring *ring, bool start, bool secure);
static void gfx_v12_0_ring_emit_wreg(struct amdgpu_ring *ring, uint32_t reg,
uint32_t val);
static int gfx_v12_0_wait_for_rlc_autoload_complete(struct amdgpu_device *adev);
@@ -4634,16 +4633,6 @@ static int gfx_v12_0_ring_preempt_ib(struct amdgpu_ring *ring)
return r;
}
static void gfx_v12_0_ring_emit_frame_cntl(struct amdgpu_ring *ring,
bool start,
bool secure)
{
uint32_t v = secure ? FRAME_TMZ : 0;
amdgpu_ring_write(ring, PACKET3(PACKET3_FRAME_CONTROL, 0));
amdgpu_ring_write(ring, v | FRAME_CMD(start ? 0 : 1));
}
static void gfx_v12_0_ring_emit_rreg(struct amdgpu_ring *ring, uint32_t reg,
uint32_t reg_val_offs)
{
@@ -5520,7 +5509,6 @@ static const struct amdgpu_ring_funcs gfx_v12_0_ring_funcs_gfx = {
.emit_cntxcntl = gfx_v12_0_ring_emit_cntxcntl,
.init_cond_exec = gfx_v12_0_ring_emit_init_cond_exec,
.preempt_ib = gfx_v12_0_ring_preempt_ib,
.emit_frame_cntl = gfx_v12_0_ring_emit_frame_cntl,
.emit_wreg = gfx_v12_0_ring_emit_wreg,
.emit_reg_wait = gfx_v12_0_ring_emit_reg_wait,
.emit_reg_write_reg_wait = gfx_v12_0_ring_emit_reg_write_reg_wait,
+1 -2
View File
@@ -120,8 +120,7 @@ static inline bool kfd_dbg_has_gws_support(struct kfd_node *dev)
&& dev->kfd->mec2_fw_version < 0x1b6) ||
(KFD_GC_VERSION(dev) == IP_VERSION(9, 4, 1)
&& dev->kfd->mec2_fw_version < 0x30) ||
(KFD_GC_VERSION(dev) >= IP_VERSION(11, 0, 0) &&
KFD_GC_VERSION(dev) < IP_VERSION(12, 0, 0)))
kfd_dbg_has_cwsr_workaround(dev))
return false;
/* Assume debugging and cooperative launch supported otherwise. */
@@ -79,7 +79,6 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
goto cleanup;
list->type = ops[i]->base.id;
list->name = kasprintf(GFP_KERNEL, "Color Pipeline %d", ops[i]->base.id);
i++;
@@ -197,6 +196,9 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
goto cleanup;
drm_colorop_set_next_property(ops[i-1], ops[i]);
list->name = kasprintf(GFP_KERNEL, "Color Pipeline %d", ops[0]->base.id);
return 0;
cleanup:
@@ -248,8 +248,6 @@ static void amdgpu_dm_crtc_vblank_control_worker(struct work_struct *work)
struct vblank_control_work *vblank_work =
container_of(work, struct vblank_control_work, work);
struct amdgpu_display_manager *dm = vblank_work->dm;
struct amdgpu_device *adev = drm_to_adev(dm->ddev);
int r;
mutex_lock(&dm->dc_lock);
@@ -279,16 +277,7 @@ static void amdgpu_dm_crtc_vblank_control_worker(struct work_struct *work)
if (dm->active_vblank_irq_count == 0) {
dc_post_update_surfaces_to_stream(dm->dc);
r = amdgpu_dpm_pause_power_profile(adev, true);
if (r)
dev_warn(adev->dev, "failed to set default power profile mode\n");
dc_allow_idle_optimizations(dm->dc, true);
r = amdgpu_dpm_pause_power_profile(adev, false);
if (r)
dev_warn(adev->dev, "failed to restore the power profile mode\n");
}
mutex_unlock(&dm->dc_lock);
@@ -915,13 +915,19 @@ void amdgpu_dm_hpd_init(struct amdgpu_device *adev)
struct amdgpu_dm_connector *amdgpu_dm_connector;
const struct dc_link *dc_link;
use_polling |= connector->polled != DRM_CONNECTOR_POLL_HPD;
if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
continue;
amdgpu_dm_connector = to_amdgpu_dm_connector(connector);
/*
* Analog connectors may be hot-plugged unlike other connector
* types that don't support HPD. Only poll analog connectors.
*/
use_polling |=
amdgpu_dm_connector->dc_link &&
dc_connector_supports_analog(amdgpu_dm_connector->dc_link->link_id.id);
dc_link = amdgpu_dm_connector->dc_link;
/*
@@ -1790,12 +1790,13 @@ dm_atomic_plane_get_property(struct drm_plane *plane,
static int
dm_plane_init_colorops(struct drm_plane *plane)
{
struct drm_prop_enum_list pipelines[MAX_COLOR_PIPELINES];
struct drm_prop_enum_list pipelines[MAX_COLOR_PIPELINES] = {};
struct drm_device *dev = plane->dev;
struct amdgpu_device *adev = drm_to_adev(dev);
struct dc *dc = adev->dm.dc;
int len = 0;
int ret;
int ret = 0;
int i;
if (plane->type == DRM_PLANE_TYPE_CURSOR)
return 0;
@@ -1806,7 +1807,7 @@ dm_plane_init_colorops(struct drm_plane *plane)
if (ret) {
drm_err(plane->dev, "Failed to create color pipeline for plane %d: %d\n",
plane->base.id, ret);
return ret;
goto out;
}
len++;
@@ -1814,7 +1815,11 @@ dm_plane_init_colorops(struct drm_plane *plane)
drm_plane_create_color_pipeline_property(plane, pipelines, len);
}
return 0;
out:
for (i = 0; i < len; i++)
kfree(pipelines[i].name);
return ret;
}
#endif
+16 -15
View File
@@ -2273,8 +2273,6 @@ static int si_populate_smc_tdp_limits(struct amdgpu_device *adev,
if (scaling_factor == 0)
return -EINVAL;
memset(smc_table, 0, sizeof(SISLANDS_SMC_STATETABLE));
ret = si_calculate_adjusted_tdp_limits(adev,
false, /* ??? */
adev->pm.dpm.tdp_adjustment,
@@ -2283,6 +2281,12 @@ static int si_populate_smc_tdp_limits(struct amdgpu_device *adev,
if (ret)
return ret;
if (adev->pdev->device == 0x6611 && adev->pdev->revision == 0x87) {
/* Workaround buggy powertune on Radeon 430 and 520. */
tdp_limit = 32;
near_tdp_limit = 28;
}
smc_table->dpm2Params.TDPLimit =
cpu_to_be32(si_scale_power_for_smc(tdp_limit, scaling_factor) * 1000);
smc_table->dpm2Params.NearTDPLimit =
@@ -2328,16 +2332,8 @@ static int si_populate_smc_tdp_limits_2(struct amdgpu_device *adev,
if (ni_pi->enable_power_containment) {
SISLANDS_SMC_STATETABLE *smc_table = &si_pi->smc_statetable;
u32 scaling_factor = si_get_smc_power_scaling_factor(adev);
int ret;
memset(smc_table, 0, sizeof(SISLANDS_SMC_STATETABLE));
smc_table->dpm2Params.NearTDPLimit =
cpu_to_be32(si_scale_power_for_smc(adev->pm.dpm.near_tdp_limit_adjusted, scaling_factor) * 1000);
smc_table->dpm2Params.SafePowerLimit =
cpu_to_be32(si_scale_power_for_smc((adev->pm.dpm.near_tdp_limit_adjusted * SISLANDS_DPM2_TDP_SAFE_LIMIT_PERCENT) / 100, scaling_factor) * 1000);
ret = amdgpu_si_copy_bytes_to_smc(adev,
(si_pi->state_table_start +
offsetof(SISLANDS_SMC_STATETABLE, dpm2Params) +
@@ -3473,10 +3469,15 @@ static void si_apply_state_adjust_rules(struct amdgpu_device *adev,
(adev->pdev->revision == 0x80) ||
(adev->pdev->revision == 0x81) ||
(adev->pdev->revision == 0x83) ||
(adev->pdev->revision == 0x87) ||
(adev->pdev->revision == 0x87 &&
adev->pdev->device != 0x6611) ||
(adev->pdev->device == 0x6604) ||
(adev->pdev->device == 0x6605)) {
max_sclk = 75000;
} else if (adev->pdev->revision == 0x87 &&
adev->pdev->device == 0x6611) {
/* Radeon 430 and 520 */
max_sclk = 78000;
}
}
@@ -7600,12 +7601,12 @@ static int si_dpm_set_interrupt_state(struct amdgpu_device *adev,
case AMDGPU_IRQ_STATE_DISABLE:
cg_thermal_int = RREG32_SMC(mmCG_THERMAL_INT);
cg_thermal_int |= CG_THERMAL_INT__THERM_INT_MASK_HIGH_MASK;
WREG32_SMC(mmCG_THERMAL_INT, cg_thermal_int);
WREG32(mmCG_THERMAL_INT, cg_thermal_int);
break;
case AMDGPU_IRQ_STATE_ENABLE:
cg_thermal_int = RREG32_SMC(mmCG_THERMAL_INT);
cg_thermal_int &= ~CG_THERMAL_INT__THERM_INT_MASK_HIGH_MASK;
WREG32_SMC(mmCG_THERMAL_INT, cg_thermal_int);
WREG32(mmCG_THERMAL_INT, cg_thermal_int);
break;
default:
break;
@@ -7617,12 +7618,12 @@ static int si_dpm_set_interrupt_state(struct amdgpu_device *adev,
case AMDGPU_IRQ_STATE_DISABLE:
cg_thermal_int = RREG32_SMC(mmCG_THERMAL_INT);
cg_thermal_int |= CG_THERMAL_INT__THERM_INT_MASK_LOW_MASK;
WREG32_SMC(mmCG_THERMAL_INT, cg_thermal_int);
WREG32(mmCG_THERMAL_INT, cg_thermal_int);
break;
case AMDGPU_IRQ_STATE_ENABLE:
cg_thermal_int = RREG32_SMC(mmCG_THERMAL_INT);
cg_thermal_int &= ~CG_THERMAL_INT__THERM_INT_MASK_LOW_MASK;
WREG32_SMC(mmCG_THERMAL_INT, cg_thermal_int);
WREG32(mmCG_THERMAL_INT, cg_thermal_int);
break;
default:
break;
+14 -6
View File
@@ -2062,33 +2062,41 @@ struct dw_dp *dw_dp_bind(struct device *dev, struct drm_encoder *encoder,
}
ret = drm_bridge_attach(encoder, bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR);
if (ret)
if (ret) {
dev_err_probe(dev, ret, "Failed to attach bridge\n");
goto unregister_aux;
}
dw_dp_init_hw(dp);
ret = phy_init(dp->phy);
if (ret) {
dev_err_probe(dev, ret, "phy init failed\n");
return ERR_PTR(ret);
goto unregister_aux;
}
ret = devm_add_action_or_reset(dev, dw_dp_phy_exit, dp);
if (ret)
return ERR_PTR(ret);
goto unregister_aux;
dp->irq = platform_get_irq(pdev, 0);
if (dp->irq < 0)
return ERR_PTR(ret);
if (dp->irq < 0) {
ret = dp->irq;
goto unregister_aux;
}
ret = devm_request_threaded_irq(dev, dp->irq, NULL, dw_dp_irq,
IRQF_ONESHOT, dev_name(dev), dp);
if (ret) {
dev_err_probe(dev, ret, "failed to request irq\n");
return ERR_PTR(ret);
goto unregister_aux;
}
return dp;
unregister_aux:
drm_dp_aux_unregister(&dp->aux);
return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(dw_dp_bind);
@@ -34,11 +34,19 @@ int _intel_color_pipeline_plane_init(struct drm_plane *plane, struct drm_prop_en
return ret;
list->type = colorop->base.base.id;
list->name = kasprintf(GFP_KERNEL, "Color Pipeline %d", colorop->base.base.id);
/* TODO: handle failures and clean up */
prev_op = &colorop->base;
colorop = intel_colorop_create(INTEL_PLANE_CB_CSC);
ret = drm_plane_colorop_ctm_3x4_init(dev, &colorop->base, plane,
DRM_COLOROP_FLAG_ALLOW_BYPASS);
if (ret)
return ret;
drm_colorop_set_next_property(prev_op, &colorop->base);
prev_op = &colorop->base;
if (DISPLAY_VER(display) >= 35 &&
intel_color_crtc_has_3dlut(display, pipe) &&
plane->type == DRM_PLANE_TYPE_PRIMARY) {
@@ -55,15 +63,6 @@ int _intel_color_pipeline_plane_init(struct drm_plane *plane, struct drm_prop_en
prev_op = &colorop->base;
}
colorop = intel_colorop_create(INTEL_PLANE_CB_CSC);
ret = drm_plane_colorop_ctm_3x4_init(dev, &colorop->base, plane,
DRM_COLOROP_FLAG_ALLOW_BYPASS);
if (ret)
return ret;
drm_colorop_set_next_property(prev_op, &colorop->base);
prev_op = &colorop->base;
colorop = intel_colorop_create(INTEL_PLANE_CB_POST_CSC_LUT);
ret = drm_plane_colorop_curve_1d_lut_init(dev, &colorop->base, plane,
PLANE_GAMMA_SIZE,
@@ -74,6 +73,8 @@ int _intel_color_pipeline_plane_init(struct drm_plane *plane, struct drm_prop_en
drm_colorop_set_next_property(prev_op, &colorop->base);
list->name = kasprintf(GFP_KERNEL, "Color Pipeline %d", list->type);
return 0;
}
@@ -81,9 +82,10 @@ int intel_color_pipeline_plane_init(struct drm_plane *plane, enum pipe pipe)
{
struct drm_device *dev = plane->dev;
struct intel_display *display = to_intel_display(dev);
struct drm_prop_enum_list pipelines[MAX_COLOR_PIPELINES];
struct drm_prop_enum_list pipelines[MAX_COLOR_PIPELINES] = {};
int len = 0;
int ret;
int ret = 0;
int i;
/* Currently expose pipeline only for HDR planes */
if (!icl_is_hdr_plane(display, to_intel_plane(plane)->id))
@@ -92,8 +94,14 @@ int intel_color_pipeline_plane_init(struct drm_plane *plane, enum pipe pipe)
/* Add pipeline consisting of transfer functions */
ret = _intel_color_pipeline_plane_init(plane, &pipelines[len], pipe);
if (ret)
return ret;
goto out;
len++;
return drm_plane_create_color_pipeline_property(plane, pipelines, len);
ret = drm_plane_create_color_pipeline_property(plane, pipelines, len);
for (i = 0; i < len; i++)
kfree(pipelines[i].name);
out:
return ret;
}
+7 -1
View File
@@ -137,6 +137,7 @@ update_logtype(struct pvr_device *pvr_dev, u32 group_mask)
struct rogue_fwif_kccb_cmd cmd;
int idx;
int err;
int slot;
if (group_mask)
fw_trace->tracebuf_ctrl->log_type = ROGUE_FWIF_LOG_TYPE_TRACE | group_mask;
@@ -154,8 +155,13 @@ update_logtype(struct pvr_device *pvr_dev, u32 group_mask)
cmd.cmd_type = ROGUE_FWIF_KCCB_CMD_LOGTYPE_UPDATE;
cmd.kccb_flags = 0;
err = pvr_kccb_send_cmd(pvr_dev, &cmd, NULL);
err = pvr_kccb_send_cmd(pvr_dev, &cmd, &slot);
if (err)
goto err_drm_dev_exit;
err = pvr_kccb_wait_for_completion(pvr_dev, slot, HZ, NULL);
err_drm_dev_exit:
drm_dev_exit(idx);
err_up_read:
+1 -1
View File
@@ -8,7 +8,7 @@ config DRM_MEDIATEK
depends on OF
depends on MTK_MMSYS
select DRM_CLIENT_SELECTION
select DRM_GEM_DMA_HELPER if DRM_FBDEV_EMULATION
select DRM_GEM_DMA_HELPER
select DRM_KMS_HELPER
select DRM_DISPLAY_HELPER
select DRM_BRIDGE_CONNECTOR
+9 -14
View File
@@ -836,20 +836,6 @@ static int mtk_dpi_bridge_attach(struct drm_bridge *bridge,
enum drm_bridge_attach_flags flags)
{
struct mtk_dpi *dpi = bridge_to_dpi(bridge);
int ret;
dpi->next_bridge = devm_drm_of_get_bridge(dpi->dev, dpi->dev->of_node, 1, -1);
if (IS_ERR(dpi->next_bridge)) {
ret = PTR_ERR(dpi->next_bridge);
if (ret == -EPROBE_DEFER)
return ret;
/* Old devicetree has only one endpoint */
dpi->next_bridge = devm_drm_of_get_bridge(dpi->dev, dpi->dev->of_node, 0, 0);
if (IS_ERR(dpi->next_bridge))
return dev_err_probe(dpi->dev, PTR_ERR(dpi->next_bridge),
"Failed to get bridge\n");
}
return drm_bridge_attach(encoder, dpi->next_bridge,
&dpi->bridge, flags);
@@ -1319,6 +1305,15 @@ static int mtk_dpi_probe(struct platform_device *pdev)
if (dpi->irq < 0)
return dpi->irq;
dpi->next_bridge = devm_drm_of_get_bridge(dpi->dev, dpi->dev->of_node, 1, -1);
if (IS_ERR(dpi->next_bridge) && PTR_ERR(dpi->next_bridge) == -ENODEV) {
/* Old devicetree has only one endpoint */
dpi->next_bridge = devm_drm_of_get_bridge(dpi->dev, dpi->dev->of_node, 0, 0);
}
if (IS_ERR(dpi->next_bridge))
return dev_err_probe(dpi->dev, PTR_ERR(dpi->next_bridge),
"Failed to get bridge\n");
platform_set_drvdata(pdev, dpi);
dpi->bridge.of_node = dev->of_node;
+103 -161
View File
@@ -1,6 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2015 MediaTek Inc.
* Copyright (c) 2025 Collabora Ltd.
* AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
*/
#include <linux/dma-buf.h>
@@ -18,24 +20,64 @@
static int mtk_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma);
static const struct vm_operations_struct vm_ops = {
.open = drm_gem_vm_open,
.close = drm_gem_vm_close,
};
static void mtk_gem_free_object(struct drm_gem_object *obj)
{
struct drm_gem_dma_object *dma_obj = to_drm_gem_dma_obj(obj);
struct mtk_drm_private *priv = obj->dev->dev_private;
if (dma_obj->sgt)
drm_prime_gem_destroy(obj, dma_obj->sgt);
else
dma_free_wc(priv->dma_dev, dma_obj->base.size,
dma_obj->vaddr, dma_obj->dma_addr);
/* release file pointer to gem object. */
drm_gem_object_release(obj);
kfree(dma_obj);
}
/*
* Allocate a sg_table for this GEM object.
* Note: Both the table's contents, and the sg_table itself must be freed by
* the caller.
* Returns a pointer to the newly allocated sg_table, or an ERR_PTR() error.
*/
static struct sg_table *mtk_gem_prime_get_sg_table(struct drm_gem_object *obj)
{
struct drm_gem_dma_object *dma_obj = to_drm_gem_dma_obj(obj);
struct mtk_drm_private *priv = obj->dev->dev_private;
struct sg_table *sgt;
int ret;
sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
if (!sgt)
return ERR_PTR(-ENOMEM);
ret = dma_get_sgtable(priv->dma_dev, sgt, dma_obj->vaddr,
dma_obj->dma_addr, obj->size);
if (ret) {
DRM_ERROR("failed to allocate sgt, %d\n", ret);
kfree(sgt);
return ERR_PTR(ret);
}
return sgt;
}
static const struct drm_gem_object_funcs mtk_gem_object_funcs = {
.free = mtk_gem_free_object,
.print_info = drm_gem_dma_object_print_info,
.get_sg_table = mtk_gem_prime_get_sg_table,
.vmap = mtk_gem_prime_vmap,
.vunmap = mtk_gem_prime_vunmap,
.vmap = drm_gem_dma_object_vmap,
.mmap = mtk_gem_object_mmap,
.vm_ops = &vm_ops,
.vm_ops = &drm_gem_dma_vm_ops,
};
static struct mtk_gem_obj *mtk_gem_init(struct drm_device *dev,
unsigned long size)
static struct drm_gem_dma_object *mtk_gem_init(struct drm_device *dev,
unsigned long size, bool private)
{
struct mtk_gem_obj *mtk_gem_obj;
struct drm_gem_dma_object *dma_obj;
int ret;
size = round_up(size, PAGE_SIZE);
@@ -43,86 +85,65 @@ static struct mtk_gem_obj *mtk_gem_init(struct drm_device *dev,
if (size == 0)
return ERR_PTR(-EINVAL);
mtk_gem_obj = kzalloc(sizeof(*mtk_gem_obj), GFP_KERNEL);
if (!mtk_gem_obj)
dma_obj = kzalloc(sizeof(*dma_obj), GFP_KERNEL);
if (!dma_obj)
return ERR_PTR(-ENOMEM);
mtk_gem_obj->base.funcs = &mtk_gem_object_funcs;
dma_obj->base.funcs = &mtk_gem_object_funcs;
ret = drm_gem_object_init(dev, &mtk_gem_obj->base, size);
if (ret < 0) {
if (private) {
ret = 0;
drm_gem_private_object_init(dev, &dma_obj->base, size);
} else {
ret = drm_gem_object_init(dev, &dma_obj->base, size);
}
if (ret) {
DRM_ERROR("failed to initialize gem object\n");
kfree(mtk_gem_obj);
kfree(dma_obj);
return ERR_PTR(ret);
}
return mtk_gem_obj;
return dma_obj;
}
struct mtk_gem_obj *mtk_gem_create(struct drm_device *dev,
size_t size, bool alloc_kmap)
static struct drm_gem_dma_object *mtk_gem_create(struct drm_device *dev, size_t size)
{
struct mtk_drm_private *priv = dev->dev_private;
struct mtk_gem_obj *mtk_gem;
struct drm_gem_dma_object *dma_obj;
struct drm_gem_object *obj;
int ret;
mtk_gem = mtk_gem_init(dev, size);
if (IS_ERR(mtk_gem))
return ERR_CAST(mtk_gem);
dma_obj = mtk_gem_init(dev, size, false);
if (IS_ERR(dma_obj))
return ERR_CAST(dma_obj);
obj = &mtk_gem->base;
obj = &dma_obj->base;
mtk_gem->dma_attrs = DMA_ATTR_WRITE_COMBINE;
if (!alloc_kmap)
mtk_gem->dma_attrs |= DMA_ATTR_NO_KERNEL_MAPPING;
mtk_gem->cookie = dma_alloc_attrs(priv->dma_dev, obj->size,
&mtk_gem->dma_addr, GFP_KERNEL,
mtk_gem->dma_attrs);
if (!mtk_gem->cookie) {
dma_obj->vaddr = dma_alloc_wc(priv->dma_dev, obj->size,
&dma_obj->dma_addr,
GFP_KERNEL | __GFP_NOWARN);
if (!dma_obj->vaddr) {
DRM_ERROR("failed to allocate %zx byte dma buffer", obj->size);
ret = -ENOMEM;
goto err_gem_free;
}
if (alloc_kmap)
mtk_gem->kvaddr = mtk_gem->cookie;
DRM_DEBUG_DRIVER("cookie = %p dma_addr = %pad size = %zu\n",
mtk_gem->cookie, &mtk_gem->dma_addr,
DRM_DEBUG_DRIVER("vaddr = %p dma_addr = %pad size = %zu\n",
dma_obj->vaddr, &dma_obj->dma_addr,
size);
return mtk_gem;
return dma_obj;
err_gem_free:
drm_gem_object_release(obj);
kfree(mtk_gem);
kfree(dma_obj);
return ERR_PTR(ret);
}
void mtk_gem_free_object(struct drm_gem_object *obj)
{
struct mtk_gem_obj *mtk_gem = to_mtk_gem_obj(obj);
struct mtk_drm_private *priv = obj->dev->dev_private;
if (mtk_gem->sg)
drm_prime_gem_destroy(obj, mtk_gem->sg);
else
dma_free_attrs(priv->dma_dev, obj->size, mtk_gem->cookie,
mtk_gem->dma_addr, mtk_gem->dma_attrs);
/* release file pointer to gem object. */
drm_gem_object_release(obj);
kfree(mtk_gem);
}
int mtk_gem_dumb_create(struct drm_file *file_priv, struct drm_device *dev,
struct drm_mode_create_dumb *args)
{
struct mtk_gem_obj *mtk_gem;
struct drm_gem_dma_object *dma_obj;
int ret;
args->pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
@@ -135,25 +156,25 @@ int mtk_gem_dumb_create(struct drm_file *file_priv, struct drm_device *dev,
args->size = args->pitch;
args->size *= args->height;
mtk_gem = mtk_gem_create(dev, args->size, false);
if (IS_ERR(mtk_gem))
return PTR_ERR(mtk_gem);
dma_obj = mtk_gem_create(dev, args->size);
if (IS_ERR(dma_obj))
return PTR_ERR(dma_obj);
/*
* allocate a id of idr table where the obj is registered
* and handle has the id what user can see.
*/
ret = drm_gem_handle_create(file_priv, &mtk_gem->base, &args->handle);
ret = drm_gem_handle_create(file_priv, &dma_obj->base, &args->handle);
if (ret)
goto err_handle_create;
/* drop reference from allocate - handle holds it now. */
drm_gem_object_put(&mtk_gem->base);
drm_gem_object_put(&dma_obj->base);
return 0;
err_handle_create:
mtk_gem_free_object(&mtk_gem->base);
mtk_gem_free_object(&dma_obj->base);
return ret;
}
@@ -161,129 +182,50 @@ static int mtk_gem_object_mmap(struct drm_gem_object *obj,
struct vm_area_struct *vma)
{
int ret;
struct mtk_gem_obj *mtk_gem = to_mtk_gem_obj(obj);
struct drm_gem_dma_object *dma_obj = to_drm_gem_dma_obj(obj);
struct mtk_drm_private *priv = obj->dev->dev_private;
int ret;
/*
* Set vm_pgoff (used as a fake buffer offset by DRM) to 0 and map the
* whole buffer from the start.
*/
vma->vm_pgoff = 0;
vma->vm_pgoff -= drm_vma_node_start(&obj->vma_node);
/*
* dma_alloc_attrs() allocated a struct page table for mtk_gem, so clear
* VM_PFNMAP flag that was set by drm_gem_mmap_obj()/drm_gem_mmap().
*/
vm_flags_set(vma, VM_IO | VM_DONTEXPAND | VM_DONTDUMP);
vm_flags_mod(vma, VM_IO | VM_DONTEXPAND | VM_DONTDUMP, VM_PFNMAP);
vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot);
ret = dma_mmap_attrs(priv->dma_dev, vma, mtk_gem->cookie,
mtk_gem->dma_addr, obj->size, mtk_gem->dma_attrs);
ret = dma_mmap_wc(priv->dma_dev, vma, dma_obj->vaddr,
dma_obj->dma_addr, obj->size);
if (ret)
drm_gem_vm_close(vma);
return ret;
}
/*
* Allocate a sg_table for this GEM object.
* Note: Both the table's contents, and the sg_table itself must be freed by
* the caller.
* Returns a pointer to the newly allocated sg_table, or an ERR_PTR() error.
*/
struct sg_table *mtk_gem_prime_get_sg_table(struct drm_gem_object *obj)
{
struct mtk_gem_obj *mtk_gem = to_mtk_gem_obj(obj);
struct mtk_drm_private *priv = obj->dev->dev_private;
struct sg_table *sgt;
int ret;
sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
if (!sgt)
return ERR_PTR(-ENOMEM);
ret = dma_get_sgtable_attrs(priv->dma_dev, sgt, mtk_gem->cookie,
mtk_gem->dma_addr, obj->size,
mtk_gem->dma_attrs);
if (ret) {
DRM_ERROR("failed to allocate sgt, %d\n", ret);
kfree(sgt);
return ERR_PTR(ret);
}
return sgt;
}
struct drm_gem_object *mtk_gem_prime_import_sg_table(struct drm_device *dev,
struct dma_buf_attachment *attach, struct sg_table *sg)
struct dma_buf_attachment *attach, struct sg_table *sgt)
{
struct mtk_gem_obj *mtk_gem;
struct drm_gem_dma_object *dma_obj;
/* check if the entries in the sg_table are contiguous */
if (drm_prime_get_contiguous_size(sg) < attach->dmabuf->size) {
if (drm_prime_get_contiguous_size(sgt) < attach->dmabuf->size) {
DRM_ERROR("sg_table is not contiguous");
return ERR_PTR(-EINVAL);
}
mtk_gem = mtk_gem_init(dev, attach->dmabuf->size);
if (IS_ERR(mtk_gem))
return ERR_CAST(mtk_gem);
dma_obj = mtk_gem_init(dev, attach->dmabuf->size, true);
if (IS_ERR(dma_obj))
return ERR_CAST(dma_obj);
mtk_gem->dma_addr = sg_dma_address(sg->sgl);
mtk_gem->sg = sg;
dma_obj->dma_addr = sg_dma_address(sgt->sgl);
dma_obj->sgt = sgt;
return &mtk_gem->base;
}
int mtk_gem_prime_vmap(struct drm_gem_object *obj, struct iosys_map *map)
{
struct mtk_gem_obj *mtk_gem = to_mtk_gem_obj(obj);
struct sg_table *sgt = NULL;
unsigned int npages;
if (mtk_gem->kvaddr)
goto out;
sgt = mtk_gem_prime_get_sg_table(obj);
if (IS_ERR(sgt))
return PTR_ERR(sgt);
npages = obj->size >> PAGE_SHIFT;
mtk_gem->pages = kcalloc(npages, sizeof(*mtk_gem->pages), GFP_KERNEL);
if (!mtk_gem->pages) {
sg_free_table(sgt);
kfree(sgt);
return -ENOMEM;
}
drm_prime_sg_to_page_array(sgt, mtk_gem->pages, npages);
mtk_gem->kvaddr = vmap(mtk_gem->pages, npages, VM_MAP,
pgprot_writecombine(PAGE_KERNEL));
if (!mtk_gem->kvaddr) {
sg_free_table(sgt);
kfree(sgt);
kfree(mtk_gem->pages);
return -ENOMEM;
}
sg_free_table(sgt);
kfree(sgt);
out:
iosys_map_set_vaddr(map, mtk_gem->kvaddr);
return 0;
}
void mtk_gem_prime_vunmap(struct drm_gem_object *obj, struct iosys_map *map)
{
struct mtk_gem_obj *mtk_gem = to_mtk_gem_obj(obj);
void *vaddr = map->vaddr;
if (!mtk_gem->pages)
return;
vunmap(vaddr);
mtk_gem->kvaddr = NULL;
kfree(mtk_gem->pages);
return &dma_obj->base;
}
+1 -32
View File
@@ -7,42 +7,11 @@
#define _MTK_GEM_H_
#include <drm/drm_gem.h>
#include <drm/drm_gem_dma_helper.h>
/*
* mtk drm buffer structure.
*
* @base: a gem object.
* - a new handle to this gem object would be created
* by drm_gem_handle_create().
* @cookie: the return value of dma_alloc_attrs(), keep it for dma_free_attrs()
* @kvaddr: kernel virtual address of gem buffer.
* @dma_addr: dma address of gem buffer.
* @dma_attrs: dma attributes of gem buffer.
*
* P.S. this object would be transferred to user as kms_bo.handle so
* user can access the buffer through kms_bo.handle.
*/
struct mtk_gem_obj {
struct drm_gem_object base;
void *cookie;
void *kvaddr;
dma_addr_t dma_addr;
unsigned long dma_attrs;
struct sg_table *sg;
struct page **pages;
};
#define to_mtk_gem_obj(x) container_of(x, struct mtk_gem_obj, base)
void mtk_gem_free_object(struct drm_gem_object *gem);
struct mtk_gem_obj *mtk_gem_create(struct drm_device *dev, size_t size,
bool alloc_kmap);
int mtk_gem_dumb_create(struct drm_file *file_priv, struct drm_device *dev,
struct drm_mode_create_dumb *args);
struct sg_table *mtk_gem_prime_get_sg_table(struct drm_gem_object *obj);
struct drm_gem_object *mtk_gem_prime_import_sg_table(struct drm_device *dev,
struct dma_buf_attachment *attach, struct sg_table *sg);
int mtk_gem_prime_vmap(struct drm_gem_object *obj, struct iosys_map *map);
void mtk_gem_prime_vunmap(struct drm_gem_object *obj, struct iosys_map *map);
#endif
+1 -1
View File
@@ -303,7 +303,7 @@ static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi, struct platform_device
return dev_err_probe(dev, ret, "Failed to get clocks\n");
hdmi->irq = platform_get_irq(pdev, 0);
if (!hdmi->irq)
if (hdmi->irq < 0)
return hdmi->irq;
hdmi->regs = device_node_to_regmap(dev->of_node);
+1 -1
View File
@@ -168,7 +168,7 @@ struct mtk_hdmi {
bool audio_enable;
bool powered;
bool enabled;
unsigned int irq;
int irq;
enum hdmi_hpd_state hpd;
hdmi_codec_plugged_cb plugged_cb;
struct device *codec_dev;
+33 -25
View File
@@ -66,11 +66,19 @@ static int mtk_ddc_check_and_rise_low_bus(struct mtk_hdmi_ddc *ddc)
return 0;
}
static int mtk_ddc_wr_one(struct mtk_hdmi_ddc *ddc, u16 addr_id,
u16 offset_id, u8 *wr_data)
static int mtk_ddcm_write_hdmi(struct mtk_hdmi_ddc *ddc, u16 addr_id,
u16 offset_id, u16 data_cnt, u8 *wr_data)
{
u32 val;
int ret;
int ret, i;
/* Don't allow transfer with a size over than the transfer fifo size
* (16 byte)
*/
if (data_cnt > 16) {
dev_err(ddc->dev, "Invalid DDCM write request\n");
return -EINVAL;
}
/* If down, rise bus for write operation */
mtk_ddc_check_and_rise_low_bus(ddc);
@@ -78,16 +86,21 @@ static int mtk_ddc_wr_one(struct mtk_hdmi_ddc *ddc, u16 addr_id,
regmap_update_bits(ddc->regs, HPD_DDC_CTRL, HPD_DDC_DELAY_CNT,
FIELD_PREP(HPD_DDC_DELAY_CNT, DDC2_DLY_CNT));
/* In case there is no payload data, just do a single write for the
* address only
*/
if (wr_data) {
regmap_write(ddc->regs, SI2C_CTRL,
FIELD_PREP(SI2C_ADDR, SI2C_ADDR_READ) |
FIELD_PREP(SI2C_WDATA, *wr_data) |
SI2C_WR);
/* Fill transfer fifo with payload data */
for (i = 0; i < data_cnt; i++) {
regmap_write(ddc->regs, SI2C_CTRL,
FIELD_PREP(SI2C_ADDR, SI2C_ADDR_READ) |
FIELD_PREP(SI2C_WDATA, wr_data[i]) |
SI2C_WR);
}
}
regmap_write(ddc->regs, DDC_CTRL,
FIELD_PREP(DDC_CTRL_CMD, DDC_CMD_SEQ_WRITE) |
FIELD_PREP(DDC_CTRL_DIN_CNT, wr_data == NULL ? 0 : 1) |
FIELD_PREP(DDC_CTRL_DIN_CNT, wr_data == NULL ? 0 : data_cnt) |
FIELD_PREP(DDC_CTRL_OFFSET, offset_id) |
FIELD_PREP(DDC_CTRL_ADDR, addr_id));
usleep_range(1000, 1250);
@@ -96,6 +109,11 @@ static int mtk_ddc_wr_one(struct mtk_hdmi_ddc *ddc, u16 addr_id,
!(val & DDC_I2C_IN_PROG), 500, 1000);
if (ret) {
dev_err(ddc->dev, "DDC I2C write timeout\n");
/* Abort transfer if it is still in progress */
regmap_update_bits(ddc->regs, DDC_CTRL, DDC_CTRL_CMD,
FIELD_PREP(DDC_CTRL_CMD, DDC_CMD_ABORT_XFER));
return ret;
}
@@ -179,6 +197,11 @@ static int mtk_ddcm_read_hdmi(struct mtk_hdmi_ddc *ddc, u16 uc_dev,
500 * (temp_length + 5));
if (ret) {
dev_err(ddc->dev, "Timeout waiting for DDC I2C\n");
/* Abort transfer if it is still in progress */
regmap_update_bits(ddc->regs, DDC_CTRL, DDC_CTRL_CMD,
FIELD_PREP(DDC_CTRL_CMD, DDC_CMD_ABORT_XFER));
return ret;
}
@@ -250,24 +273,9 @@ static int mtk_hdmi_fg_ddc_data_read(struct mtk_hdmi_ddc *ddc, u16 b_dev,
static int mtk_hdmi_ddc_fg_data_write(struct mtk_hdmi_ddc *ddc, u16 b_dev,
u8 data_addr, u16 data_cnt, u8 *pr_data)
{
int i, ret;
regmap_set_bits(ddc->regs, HDCP2X_POL_CTRL, HDCP2X_DIS_POLL_EN);
/*
* In case there is no payload data, just do a single write for the
* address only
*/
if (data_cnt == 0)
return mtk_ddc_wr_one(ddc, b_dev, data_addr, NULL);
i = 0;
do {
ret = mtk_ddc_wr_one(ddc, b_dev, data_addr + i, pr_data + i);
if (ret)
return ret;
} while (++i < data_cnt);
return 0;
return mtk_ddcm_write_hdmi(ddc, b_dev, data_addr, data_cnt, pr_data);
}
static int mtk_hdmi_ddc_v2_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
+4 -3
View File
@@ -1120,9 +1120,10 @@ static void mtk_hdmi_v2_hpd_disable(struct drm_bridge *bridge)
mtk_hdmi_v2_disable(hdmi);
}
static int mtk_hdmi_v2_hdmi_tmds_char_rate_valid(const struct drm_bridge *bridge,
const struct drm_display_mode *mode,
unsigned long long tmds_rate)
static enum drm_mode_status
mtk_hdmi_v2_hdmi_tmds_char_rate_valid(const struct drm_bridge *bridge,
const struct drm_display_mode *mode,
unsigned long long tmds_rate)
{
if (mode->clock < MTK_HDMI_V2_CLOCK_MIN)
return MODE_CLOCK_LOW;
+4 -4
View File
@@ -11,13 +11,13 @@
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_print.h>
#include <linux/align.h>
#include "mtk_crtc.h"
#include "mtk_ddp_comp.h"
#include "mtk_drm_drv.h"
#include "mtk_gem.h"
#include "mtk_plane.h"
static const u64 modifiers[] = {
@@ -114,8 +114,8 @@ static void mtk_plane_update_new_state(struct drm_plane_state *new_state,
struct mtk_plane_state *mtk_plane_state)
{
struct drm_framebuffer *fb = new_state->fb;
struct drm_gem_dma_object *dma_obj;
struct drm_gem_object *gem;
struct mtk_gem_obj *mtk_gem;
unsigned int pitch, format;
u64 modifier;
dma_addr_t addr;
@@ -124,8 +124,8 @@ static void mtk_plane_update_new_state(struct drm_plane_state *new_state,
int offset;
gem = fb->obj[0];
mtk_gem = to_mtk_gem_obj(gem);
addr = mtk_gem->dma_addr;
dma_obj = to_drm_gem_dma_obj(gem);
addr = dma_obj->dma_addr;
pitch = fb->pitches[0];
format = fb->format->format;
modifier = fb->modifier;
@@ -1,28 +1,81 @@
/* SPDX-License-Identifier: MIT */
#ifndef __NVBIOS_CONN_H__
#define __NVBIOS_CONN_H__
/*
* An enumerator representing all of the possible VBIOS connector types defined
* by Nvidia at
* https://nvidia.github.io/open-gpu-doc/DCB/DCB-4.x-Specification.html.
*
* [1] Nvidia's documentation actually claims DCB_CONNECTOR_HDMI_0 is a "3-Pin
* DIN Stereo Connector". This seems very likely to be a documentation typo
* or some sort of funny historical baggage, because we've treated this
* connector type as HDMI for years without issue.
* TODO: Check with Nvidia what's actually happening here.
*/
enum dcb_connector_type {
DCB_CONNECTOR_VGA = 0x00,
DCB_CONNECTOR_TV_0 = 0x10,
DCB_CONNECTOR_TV_1 = 0x11,
DCB_CONNECTOR_TV_3 = 0x13,
DCB_CONNECTOR_DVI_I = 0x30,
DCB_CONNECTOR_DVI_D = 0x31,
DCB_CONNECTOR_DMS59_0 = 0x38,
DCB_CONNECTOR_DMS59_1 = 0x39,
DCB_CONNECTOR_LVDS = 0x40,
DCB_CONNECTOR_LVDS_SPWG = 0x41,
DCB_CONNECTOR_DP = 0x46,
DCB_CONNECTOR_eDP = 0x47,
DCB_CONNECTOR_mDP = 0x48,
DCB_CONNECTOR_HDMI_0 = 0x60,
DCB_CONNECTOR_HDMI_1 = 0x61,
DCB_CONNECTOR_HDMI_C = 0x63,
DCB_CONNECTOR_DMS59_DP0 = 0x64,
DCB_CONNECTOR_DMS59_DP1 = 0x65,
DCB_CONNECTOR_WFD = 0x70,
DCB_CONNECTOR_USB_C = 0x71,
DCB_CONNECTOR_NONE = 0xff
/* Analog outputs */
DCB_CONNECTOR_VGA = 0x00, // VGA 15-pin connector
DCB_CONNECTOR_DVI_A = 0x01, // DVI-A
DCB_CONNECTOR_POD_VGA = 0x02, // Pod - VGA 15-pin connector
DCB_CONNECTOR_TV_0 = 0x10, // TV - Composite Out
DCB_CONNECTOR_TV_1 = 0x11, // TV - S-Video Out
DCB_CONNECTOR_TV_2 = 0x12, // TV - S-Video Breakout - Composite
DCB_CONNECTOR_TV_3 = 0x13, // HDTV Component - YPrPb
DCB_CONNECTOR_TV_SCART = 0x14, // TV - SCART Connector
DCB_CONNECTOR_TV_SCART_D = 0x16, // TV - Composite SCART over D-connector
DCB_CONNECTOR_TV_DTERM = 0x17, // HDTV - D-connector (EIAJ4120)
DCB_CONNECTOR_POD_TV_3 = 0x18, // Pod - HDTV - YPrPb
DCB_CONNECTOR_POD_TV_1 = 0x19, // Pod - S-Video
DCB_CONNECTOR_POD_TV_0 = 0x1a, // Pod - Composite
/* DVI digital outputs */
DCB_CONNECTOR_DVI_I_TV_1 = 0x20, // DVI-I-TV-S-Video
DCB_CONNECTOR_DVI_I_TV_0 = 0x21, // DVI-I-TV-Composite
DCB_CONNECTOR_DVI_I_TV_2 = 0x22, // DVI-I-TV-S-Video Breakout-Composite
DCB_CONNECTOR_DVI_I = 0x30, // DVI-I
DCB_CONNECTOR_DVI_D = 0x31, // DVI-D
DCB_CONNECTOR_DVI_ADC = 0x32, // Apple Display Connector (ADC)
DCB_CONNECTOR_DMS59_0 = 0x38, // LFH-DVI-I-1
DCB_CONNECTOR_DMS59_1 = 0x39, // LFH-DVI-I-2
DCB_CONNECTOR_BNC = 0x3c, // BNC Connector [for SDI?]
/* LVDS / TMDS digital outputs */
DCB_CONNECTOR_LVDS = 0x40, // LVDS-SPWG-Attached [is this name correct?]
DCB_CONNECTOR_LVDS_SPWG = 0x41, // LVDS-OEM-Attached (non-removable)
DCB_CONNECTOR_LVDS_REM = 0x42, // LVDS-SPWG-Detached [following naming above]
DCB_CONNECTOR_LVDS_SPWG_REM = 0x43, // LVDS-OEM-Detached (removable)
DCB_CONNECTOR_TMDS = 0x45, // TMDS-OEM-Attached (non-removable)
/* DP digital outputs */
DCB_CONNECTOR_DP = 0x46, // DisplayPort External Connector
DCB_CONNECTOR_eDP = 0x47, // DisplayPort Internal Connector
DCB_CONNECTOR_mDP = 0x48, // DisplayPort (Mini) External Connector
/* Dock outputs (not used) */
DCB_CONNECTOR_DOCK_VGA_0 = 0x50, // VGA 15-pin if not docked
DCB_CONNECTOR_DOCK_VGA_1 = 0x51, // VGA 15-pin if docked
DCB_CONNECTOR_DOCK_DVI_I_0 = 0x52, // DVI-I if not docked
DCB_CONNECTOR_DOCK_DVI_I_1 = 0x53, // DVI-I if docked
DCB_CONNECTOR_DOCK_DVI_D_0 = 0x54, // DVI-D if not docked
DCB_CONNECTOR_DOCK_DVI_D_1 = 0x55, // DVI-D if docked
DCB_CONNECTOR_DOCK_DP_0 = 0x56, // DisplayPort if not docked
DCB_CONNECTOR_DOCK_DP_1 = 0x57, // DisplayPort if docked
DCB_CONNECTOR_DOCK_mDP_0 = 0x58, // DisplayPort (Mini) if not docked
DCB_CONNECTOR_DOCK_mDP_1 = 0x59, // DisplayPort (Mini) if docked
/* HDMI? digital outputs */
DCB_CONNECTOR_HDMI_0 = 0x60, // HDMI? See [1] in top-level enum comment above
DCB_CONNECTOR_HDMI_1 = 0x61, // HDMI-A connector
DCB_CONNECTOR_SPDIF = 0x62, // Audio S/PDIF connector
DCB_CONNECTOR_HDMI_C = 0x63, // HDMI-C (Mini) connector
/* Misc. digital outputs */
DCB_CONNECTOR_DMS59_DP0 = 0x64, // LFH-DP-1
DCB_CONNECTOR_DMS59_DP1 = 0x65, // LFH-DP-2
DCB_CONNECTOR_WFD = 0x70, // Virtual connector for Wifi Display (WFD)
DCB_CONNECTOR_USB_C = 0x71, // [DP over USB-C; not present in docs]
DCB_CONNECTOR_NONE = 0xff // Skip Entry
};
struct nvbios_connT {
@@ -352,6 +352,8 @@ nouveau_user_framebuffer_create(struct drm_device *dev,
static const struct drm_mode_config_funcs nouveau_mode_config_funcs = {
.fb_create = nouveau_user_framebuffer_create,
.atomic_commit = drm_atomic_helper_commit,
.atomic_check = drm_atomic_helper_check,
};
@@ -191,27 +191,60 @@ nvkm_uconn_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, struct nv
spin_lock(&disp->client.lock);
if (!conn->object.func) {
switch (conn->info.type) {
case DCB_CONNECTOR_VGA : args->v0.type = NVIF_CONN_V0_VGA; break;
case DCB_CONNECTOR_TV_0 :
case DCB_CONNECTOR_TV_1 :
case DCB_CONNECTOR_TV_3 : args->v0.type = NVIF_CONN_V0_TV; break;
case DCB_CONNECTOR_DMS59_0 :
case DCB_CONNECTOR_DMS59_1 :
case DCB_CONNECTOR_DVI_I : args->v0.type = NVIF_CONN_V0_DVI_I; break;
case DCB_CONNECTOR_DVI_D : args->v0.type = NVIF_CONN_V0_DVI_D; break;
case DCB_CONNECTOR_LVDS : args->v0.type = NVIF_CONN_V0_LVDS; break;
case DCB_CONNECTOR_LVDS_SPWG: args->v0.type = NVIF_CONN_V0_LVDS_SPWG; break;
case DCB_CONNECTOR_DMS59_DP0:
case DCB_CONNECTOR_DMS59_DP1:
case DCB_CONNECTOR_DP :
case DCB_CONNECTOR_mDP :
case DCB_CONNECTOR_USB_C : args->v0.type = NVIF_CONN_V0_DP; break;
case DCB_CONNECTOR_eDP : args->v0.type = NVIF_CONN_V0_EDP; break;
case DCB_CONNECTOR_HDMI_0 :
case DCB_CONNECTOR_HDMI_1 :
case DCB_CONNECTOR_HDMI_C : args->v0.type = NVIF_CONN_V0_HDMI; break;
/* VGA */
case DCB_CONNECTOR_DVI_A :
case DCB_CONNECTOR_POD_VGA :
case DCB_CONNECTOR_VGA : args->v0.type = NVIF_CONN_V0_VGA; break;
/* TV */
case DCB_CONNECTOR_TV_0 :
case DCB_CONNECTOR_TV_1 :
case DCB_CONNECTOR_TV_2 :
case DCB_CONNECTOR_TV_SCART :
case DCB_CONNECTOR_TV_SCART_D :
case DCB_CONNECTOR_TV_DTERM :
case DCB_CONNECTOR_POD_TV_3 :
case DCB_CONNECTOR_POD_TV_1 :
case DCB_CONNECTOR_POD_TV_0 :
case DCB_CONNECTOR_TV_3 : args->v0.type = NVIF_CONN_V0_TV; break;
/* DVI */
case DCB_CONNECTOR_DVI_I_TV_1 :
case DCB_CONNECTOR_DVI_I_TV_0 :
case DCB_CONNECTOR_DVI_I_TV_2 :
case DCB_CONNECTOR_DVI_ADC :
case DCB_CONNECTOR_DMS59_0 :
case DCB_CONNECTOR_DMS59_1 :
case DCB_CONNECTOR_DVI_I : args->v0.type = NVIF_CONN_V0_DVI_I; break;
case DCB_CONNECTOR_TMDS :
case DCB_CONNECTOR_DVI_D : args->v0.type = NVIF_CONN_V0_DVI_D; break;
/* LVDS */
case DCB_CONNECTOR_LVDS : args->v0.type = NVIF_CONN_V0_LVDS; break;
case DCB_CONNECTOR_LVDS_SPWG : args->v0.type = NVIF_CONN_V0_LVDS_SPWG; break;
/* DP */
case DCB_CONNECTOR_DMS59_DP0 :
case DCB_CONNECTOR_DMS59_DP1 :
case DCB_CONNECTOR_DP :
case DCB_CONNECTOR_mDP :
case DCB_CONNECTOR_USB_C : args->v0.type = NVIF_CONN_V0_DP; break;
case DCB_CONNECTOR_eDP : args->v0.type = NVIF_CONN_V0_EDP; break;
/* HDMI */
case DCB_CONNECTOR_HDMI_0 :
case DCB_CONNECTOR_HDMI_1 :
case DCB_CONNECTOR_HDMI_C : args->v0.type = NVIF_CONN_V0_HDMI; break;
/*
* Dock & unused outputs.
* BNC, SPDIF, WFD, and detached LVDS go here.
*/
default:
WARN_ON(1);
nvkm_warn(&disp->engine.subdev,
"unimplemented connector type 0x%02x\n",
conn->info.type);
args->v0.type = NVIF_CONN_V0_VGA;
ret = -EINVAL;
break;
}
+8 -7
View File
@@ -37,7 +37,6 @@ static int vkms_initialize_color_pipeline(struct drm_plane *plane, struct drm_pr
goto cleanup;
list->type = ops[i]->base.id;
list->name = kasprintf(GFP_KERNEL, "Color Pipeline %d", ops[i]->base.id);
i++;
@@ -88,6 +87,8 @@ static int vkms_initialize_color_pipeline(struct drm_plane *plane, struct drm_pr
drm_colorop_set_next_property(ops[i - 1], ops[i]);
list->name = kasprintf(GFP_KERNEL, "Color Pipeline %d", ops[0]->base.id);
return 0;
cleanup:
@@ -103,18 +104,18 @@ cleanup:
int vkms_initialize_colorops(struct drm_plane *plane)
{
struct drm_prop_enum_list pipeline;
int ret;
struct drm_prop_enum_list pipeline = {};
int ret = 0;
/* Add color pipeline */
ret = vkms_initialize_color_pipeline(plane, &pipeline);
if (ret)
return ret;
goto out;
/* Create COLOR_PIPELINE property and attach */
ret = drm_plane_create_color_pipeline_property(plane, &pipeline, 1);
if (ret)
return ret;
return 0;
kfree(pipeline.name);
out:
return ret;
}
+3 -2
View File
@@ -39,7 +39,7 @@ config DRM_XE
select DRM_TTM
select DRM_TTM_HELPER
select DRM_EXEC
select DRM_GPUSVM if !UML && DEVICE_PRIVATE
select DRM_GPUSVM if !UML
select DRM_GPUVM
select DRM_SCHED
select MMU_NOTIFIER
@@ -80,8 +80,9 @@ config DRM_XE_GPUSVM
bool "Enable CPU to GPU address mirroring"
depends on DRM_XE
depends on !UML
depends on DEVICE_PRIVATE
depends on ZONE_DEVICE
default y
select DEVICE_PRIVATE
select DRM_GPUSVM
help
Enable this option if you want support for CPU to GPU address
+7 -2
View File
@@ -1055,6 +1055,7 @@ static long xe_bo_shrink_purge(struct ttm_operation_ctx *ctx,
unsigned long *scanned)
{
struct xe_device *xe = ttm_to_xe_device(bo->bdev);
struct ttm_tt *tt = bo->ttm;
long lret;
/* Fake move to system, without copying data. */
@@ -1079,8 +1080,10 @@ static long xe_bo_shrink_purge(struct ttm_operation_ctx *ctx,
.writeback = false,
.allow_move = false});
if (lret > 0)
if (lret > 0) {
xe_ttm_tt_account_subtract(xe, bo->ttm);
update_global_total_pages(bo->bdev, -(long)tt->num_pages);
}
return lret;
}
@@ -1166,8 +1169,10 @@ long xe_bo_shrink(struct ttm_operation_ctx *ctx, struct ttm_buffer_object *bo,
if (needs_rpm)
xe_pm_runtime_put(xe);
if (lret > 0)
if (lret > 0) {
xe_ttm_tt_account_subtract(xe, tt);
update_global_total_pages(bo->bdev, -(long)tt->num_pages);
}
out_unref:
xe_bo_put(xe_bo);
+57 -15
View File
@@ -256,14 +256,64 @@ static ssize_t wedged_mode_show(struct file *f, char __user *ubuf,
return simple_read_from_buffer(ubuf, size, pos, buf, len);
}
static int __wedged_mode_set_reset_policy(struct xe_gt *gt, enum xe_wedged_mode mode)
{
bool enable_engine_reset;
int ret;
enable_engine_reset = (mode != XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET);
ret = xe_guc_ads_scheduler_policy_toggle_reset(&gt->uc.guc.ads,
enable_engine_reset);
if (ret)
xe_gt_err(gt, "Failed to update GuC ADS scheduler policy (%pe)\n", ERR_PTR(ret));
return ret;
}
static int wedged_mode_set_reset_policy(struct xe_device *xe, enum xe_wedged_mode mode)
{
struct xe_gt *gt;
int ret;
u8 id;
guard(xe_pm_runtime)(xe);
for_each_gt(gt, xe, id) {
ret = __wedged_mode_set_reset_policy(gt, mode);
if (ret) {
if (id > 0) {
xe->wedged.inconsistent_reset = true;
drm_err(&xe->drm, "Inconsistent reset policy state between GTs\n");
}
return ret;
}
}
xe->wedged.inconsistent_reset = false;
return 0;
}
static bool wedged_mode_needs_policy_update(struct xe_device *xe, enum xe_wedged_mode mode)
{
if (xe->wedged.inconsistent_reset)
return true;
if (xe->wedged.mode == mode)
return false;
if (xe->wedged.mode == XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET ||
mode == XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET)
return true;
return false;
}
static ssize_t wedged_mode_set(struct file *f, const char __user *ubuf,
size_t size, loff_t *pos)
{
struct xe_device *xe = file_inode(f)->i_private;
struct xe_gt *gt;
u32 wedged_mode;
ssize_t ret;
u8 id;
ret = kstrtouint_from_user(ubuf, size, 0, &wedged_mode);
if (ret)
@@ -272,22 +322,14 @@ static ssize_t wedged_mode_set(struct file *f, const char __user *ubuf,
if (wedged_mode > 2)
return -EINVAL;
if (xe->wedged.mode == wedged_mode)
return size;
if (wedged_mode_needs_policy_update(xe, wedged_mode)) {
ret = wedged_mode_set_reset_policy(xe, wedged_mode);
if (ret)
return ret;
}
xe->wedged.mode = wedged_mode;
xe_pm_runtime_get(xe);
for_each_gt(gt, xe, id) {
ret = xe_guc_ads_scheduler_policy_toggle_reset(&gt->uc.guc.ads);
if (ret) {
xe_gt_err(gt, "Failed to update GuC ADS scheduler policy. GuC may still cause engine reset even with wedged_mode=2\n");
xe_pm_runtime_put(xe);
return -EIO;
}
}
xe_pm_runtime_put(xe);
return size;
}
+18
View File
@@ -44,6 +44,22 @@ struct xe_pat_ops;
struct xe_pxp;
struct xe_vram_region;
/**
* enum xe_wedged_mode - possible wedged modes
* @XE_WEDGED_MODE_NEVER: Device will never be declared wedged.
* @XE_WEDGED_MODE_UPON_CRITICAL_ERROR: Device will be declared wedged only
* when critical error occurs like GT reset failure or firmware failure.
* This is the default mode.
* @XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET: Device will be declared wedged on
* any hang. In this mode, engine resets are disabled to avoid automatic
* recovery attempts. This mode is primarily intended for debugging hangs.
*/
enum xe_wedged_mode {
XE_WEDGED_MODE_NEVER = 0,
XE_WEDGED_MODE_UPON_CRITICAL_ERROR = 1,
XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET = 2,
};
#define XE_BO_INVALID_OFFSET LONG_MAX
#define GRAPHICS_VER(xe) ((xe)->info.graphics_verx100 / 100)
@@ -587,6 +603,8 @@ struct xe_device {
int mode;
/** @wedged.method: Recovery method to be sent in the drm device wedged uevent */
unsigned long method;
/** @wedged.inconsistent_reset: Inconsistent reset policy state between GTs */
bool inconsistent_reset;
} wedged;
/** @bo_device: Struct to control async free of BOs */
+31 -1
View File
@@ -328,6 +328,7 @@ struct xe_exec_queue *xe_exec_queue_create_class(struct xe_device *xe, struct xe
* @xe: Xe device.
* @tile: tile which bind exec queue belongs to.
* @flags: exec queue creation flags
* @user_vm: The user VM which this exec queue belongs to
* @extensions: exec queue creation extensions
*
* Normalize bind exec queue creation. Bind exec queue is tied to migration VM
@@ -341,6 +342,7 @@ struct xe_exec_queue *xe_exec_queue_create_class(struct xe_device *xe, struct xe
*/
struct xe_exec_queue *xe_exec_queue_create_bind(struct xe_device *xe,
struct xe_tile *tile,
struct xe_vm *user_vm,
u32 flags, u64 extensions)
{
struct xe_gt *gt = tile->primary_gt;
@@ -377,6 +379,9 @@ struct xe_exec_queue *xe_exec_queue_create_bind(struct xe_device *xe,
xe_exec_queue_put(q);
return ERR_PTR(err);
}
if (user_vm)
q->user_vm = xe_vm_get(user_vm);
}
return q;
@@ -407,6 +412,11 @@ void xe_exec_queue_destroy(struct kref *ref)
xe_exec_queue_put(eq);
}
if (q->user_vm) {
xe_vm_put(q->user_vm);
q->user_vm = NULL;
}
q->ops->destroy(q);
}
@@ -742,6 +752,22 @@ int xe_exec_queue_create_ioctl(struct drm_device *dev, void *data,
XE_IOCTL_DBG(xe, eci[0].engine_instance != 0))
return -EINVAL;
vm = xe_vm_lookup(xef, args->vm_id);
if (XE_IOCTL_DBG(xe, !vm))
return -ENOENT;
err = down_read_interruptible(&vm->lock);
if (err) {
xe_vm_put(vm);
return err;
}
if (XE_IOCTL_DBG(xe, xe_vm_is_closed_or_banned(vm))) {
up_read(&vm->lock);
xe_vm_put(vm);
return -ENOENT;
}
for_each_tile(tile, xe, id) {
struct xe_exec_queue *new;
@@ -749,9 +775,11 @@ int xe_exec_queue_create_ioctl(struct drm_device *dev, void *data,
if (id)
flags |= EXEC_QUEUE_FLAG_BIND_ENGINE_CHILD;
new = xe_exec_queue_create_bind(xe, tile, flags,
new = xe_exec_queue_create_bind(xe, tile, vm, flags,
args->extensions);
if (IS_ERR(new)) {
up_read(&vm->lock);
xe_vm_put(vm);
err = PTR_ERR(new);
if (q)
goto put_exec_queue;
@@ -763,6 +791,8 @@ int xe_exec_queue_create_ioctl(struct drm_device *dev, void *data,
list_add_tail(&new->multi_gt_list,
&q->multi_gt_link);
}
up_read(&vm->lock);
xe_vm_put(vm);
} else {
logical_mask = calc_validate_logical_mask(xe, eci,
args->width,
+1
View File
@@ -28,6 +28,7 @@ struct xe_exec_queue *xe_exec_queue_create_class(struct xe_device *xe, struct xe
u32 flags, u64 extensions);
struct xe_exec_queue *xe_exec_queue_create_bind(struct xe_device *xe,
struct xe_tile *tile,
struct xe_vm *user_vm,
u32 flags, u64 extensions);
void xe_exec_queue_fini(struct xe_exec_queue *q);
+6
View File
@@ -54,6 +54,12 @@ struct xe_exec_queue {
struct kref refcount;
/** @vm: VM (address space) for this exec queue */
struct xe_vm *vm;
/**
* @user_vm: User VM (address space) for this exec queue (bind queues
* only)
*/
struct xe_vm *user_vm;
/** @class: class of this exec queue */
enum xe_engine_class class;
/**
+1 -1
View File
@@ -322,7 +322,7 @@ int xe_ggtt_init_early(struct xe_ggtt *ggtt)
else
ggtt->pt_ops = &xelp_pt_ops;
ggtt->wq = alloc_workqueue("xe-ggtt-wq", 0, WQ_MEM_RECLAIM);
ggtt->wq = alloc_workqueue("xe-ggtt-wq", WQ_MEM_RECLAIM, 0);
if (!ggtt->wq)
return -ENOMEM;
+2 -2
View File
@@ -41,10 +41,10 @@ struct xe_gt_sriov_vf_runtime {
};
/**
* xe_gt_sriov_vf_migration - VF migration data.
* struct xe_gt_sriov_vf_migration - VF migration data.
*/
struct xe_gt_sriov_vf_migration {
/** @migration: VF migration recovery worker */
/** @worker: VF migration recovery worker */
struct work_struct worker;
/** @lock: Protects recovery_queued, teardown */
spinlock_t lock;
+8 -6
View File
@@ -983,16 +983,17 @@ static int guc_ads_action_update_policies(struct xe_guc_ads *ads, u32 policy_off
/**
* xe_guc_ads_scheduler_policy_toggle_reset - Toggle reset policy
* @ads: Additional data structures object
* @enable_engine_reset: true to enable engine resets, false otherwise
*
* This function update the GuC's engine reset policy based on wedged.mode.
* This function update the GuC's engine reset policy.
*
* Return: 0 on success, and negative error code otherwise.
*/
int xe_guc_ads_scheduler_policy_toggle_reset(struct xe_guc_ads *ads)
int xe_guc_ads_scheduler_policy_toggle_reset(struct xe_guc_ads *ads,
bool enable_engine_reset)
{
struct guc_policies *policies;
struct xe_guc *guc = ads_to_guc(ads);
struct xe_device *xe = ads_to_xe(ads);
CLASS(xe_guc_buf, buf)(&guc->buf, sizeof(*policies));
if (!xe_guc_buf_is_valid(buf))
@@ -1004,10 +1005,11 @@ int xe_guc_ads_scheduler_policy_toggle_reset(struct xe_guc_ads *ads)
policies->dpc_promote_time = ads_blob_read(ads, policies.dpc_promote_time);
policies->max_num_work_items = ads_blob_read(ads, policies.max_num_work_items);
policies->is_valid = 1;
if (xe->wedged.mode == 2)
policies->global_flags |= GLOBAL_POLICY_DISABLE_ENGINE_RESET;
else
if (enable_engine_reset)
policies->global_flags &= ~GLOBAL_POLICY_DISABLE_ENGINE_RESET;
else
policies->global_flags |= GLOBAL_POLICY_DISABLE_ENGINE_RESET;
return guc_ads_action_update_policies(ads, xe_guc_buf_flush(buf));
}
+4 -1
View File
@@ -6,6 +6,8 @@
#ifndef _XE_GUC_ADS_H_
#define _XE_GUC_ADS_H_
#include <linux/types.h>
struct xe_guc_ads;
int xe_guc_ads_init(struct xe_guc_ads *ads);
@@ -13,6 +15,7 @@ int xe_guc_ads_init_post_hwconfig(struct xe_guc_ads *ads);
void xe_guc_ads_populate(struct xe_guc_ads *ads);
void xe_guc_ads_populate_minimal(struct xe_guc_ads *ads);
void xe_guc_ads_populate_post_load(struct xe_guc_ads *ads);
int xe_guc_ads_scheduler_policy_toggle_reset(struct xe_guc_ads *ads);
int xe_guc_ads_scheduler_policy_toggle_reset(struct xe_guc_ads *ads,
bool enable_engine_reset);
#endif
+3 -1
View File
@@ -15,10 +15,12 @@
#define XE_LB_MAX_PAYLOAD_SIZE SZ_4K
/**
* xe_late_bind_fw_id - enum to determine late binding fw index
* enum xe_late_bind_fw_id - enum to determine late binding fw index
*/
enum xe_late_bind_fw_id {
/** @XE_LB_FW_FAN_CONTROL: Fan control */
XE_LB_FW_FAN_CONTROL = 0,
/** @XE_LB_FW_MAX_ID: Number of IDs */
XE_LB_FW_MAX_ID
};
+3
View File
@@ -1050,6 +1050,9 @@ static ssize_t setup_utilization_wa(struct xe_lrc *lrc,
{
u32 *cmd = batch;
if (IS_SRIOV_VF(gt_to_xe(lrc->gt)))
return 0;
if (xe_gt_WARN_ON(lrc->gt, max_len < 12))
return -ENOSPC;
+2 -2
View File
@@ -2445,7 +2445,7 @@ void xe_migrate_job_lock(struct xe_migrate *m, struct xe_exec_queue *q)
if (is_migrate)
mutex_lock(&m->job_mutex);
else
xe_vm_assert_held(q->vm); /* User queues VM's should be locked */
xe_vm_assert_held(q->user_vm); /* User queues VM's should be locked */
}
/**
@@ -2463,7 +2463,7 @@ void xe_migrate_job_unlock(struct xe_migrate *m, struct xe_exec_queue *q)
if (is_migrate)
mutex_unlock(&m->job_mutex);
else
xe_vm_assert_held(q->vm); /* User queues VM's should be locked */
xe_vm_assert_held(q->user_vm); /* User queues VM's should be locked */
}
#if IS_ENABLED(CONFIG_PROVE_LOCKING)
+1 -1
View File
@@ -346,7 +346,7 @@ int xe_sriov_vf_ccs_init(struct xe_device *xe)
flags = EXEC_QUEUE_FLAG_KERNEL |
EXEC_QUEUE_FLAG_PERMANENT |
EXEC_QUEUE_FLAG_MIGRATE;
q = xe_exec_queue_create_bind(xe, tile, flags, 0);
q = xe_exec_queue_create_bind(xe, tile, NULL, flags, 0);
if (IS_ERR(q)) {
err = PTR_ERR(q);
goto err_ret;
+6 -1
View File
@@ -1617,7 +1617,7 @@ struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags, struct xe_file *xef)
if (!vm->pt_root[id])
continue;
q = xe_exec_queue_create_bind(xe, tile, create_flags, 0);
q = xe_exec_queue_create_bind(xe, tile, vm, create_flags, 0);
if (IS_ERR(q)) {
err = PTR_ERR(q);
goto err_close;
@@ -3578,6 +3578,11 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
}
}
if (XE_IOCTL_DBG(xe, q && vm != q->user_vm)) {
err = -EINVAL;
goto put_exec_queue;
}
/* Ensure all UNMAPs visible */
xe_svm_flush(vm);
+1 -1
View File
@@ -379,7 +379,7 @@ static inline void xe_vm_set_validation_exec(struct xe_vm *vm, struct drm_exec *
}
/**
* xe_vm_set_validation_exec() - Accessor to read the drm_exec object
* xe_vm_validation_exec() - Accessor to read the drm_exec object
* @vm: The vm we want to register a drm_exec object with.
*
* Return: The drm_exec object used to lock the vm's resv. The value
+17 -2
View File
@@ -209,6 +209,19 @@ struct drm_pagemap_devmem_ops {
struct dma_fence *pre_migrate_fence);
};
#if IS_ENABLED(CONFIG_ZONE_DEVICE)
struct drm_pagemap *drm_pagemap_page_to_dpagemap(struct page *page);
#else
static inline struct drm_pagemap *drm_pagemap_page_to_dpagemap(struct page *page)
{
return NULL;
}
#endif /* IS_ENABLED(CONFIG_ZONE_DEVICE) */
/**
* struct drm_pagemap_devmem - Structure representing a GPU SVM device memory allocation
*
@@ -233,6 +246,8 @@ struct drm_pagemap_devmem {
struct dma_fence *pre_migrate_fence;
};
#if IS_ENABLED(CONFIG_ZONE_DEVICE)
int drm_pagemap_migrate_to_devmem(struct drm_pagemap_devmem *devmem_allocation,
struct mm_struct *mm,
unsigned long start, unsigned long end,
@@ -243,8 +258,6 @@ int drm_pagemap_evict_to_ram(struct drm_pagemap_devmem *devmem_allocation);
const struct dev_pagemap_ops *drm_pagemap_pagemap_ops_get(void);
struct drm_pagemap *drm_pagemap_page_to_dpagemap(struct page *page);
void drm_pagemap_devmem_init(struct drm_pagemap_devmem *devmem_allocation,
struct device *dev, struct mm_struct *mm,
const struct drm_pagemap_devmem_ops *ops,
@@ -256,4 +269,6 @@ int drm_pagemap_populate_mm(struct drm_pagemap *dpagemap,
struct mm_struct *mm,
unsigned long timeslice_ms);
#endif /* IS_ENABLED(CONFIG_ZONE_DEVICE) */
#endif