drm fixes for 6.14-rc5
amdgpu: - Legacy dpm suspend/resume fix - Runtime PM fix for DELL G5 SE - MAINTAINERS updates - Enforce Isolation fixes - mailmap update - EDID reading i2c fix - PSR fix - eDP fix - HPD interrupt handling fix - Clear memory fix amdkfd: - MQD handling fix vkms: - fix rounding error imagination: - header fix nouveau: - connector status fix fb/defio: - NULL ptr fix for defio drivers i915: - Fix encoder HW state readout for DP UHBR MST xe: - OA uapi fix (Umesh) - Userptr related fixes - Remove a duplicated register entry - Scheduler related fix to prevent exec races when freeing it -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEEKbZHaGwW9KfbeusDHTzWXnEhr4FAmfBJsEACgkQDHTzWXnE hr6TyRAAp7uHGMiThuMvWlm9fY9OG6HP9aCgz0leakpiX6JDm4VWM/MChhbrHSTs de9e2iCJ8Crx97FG0jholfglNnqsQvdG8Th3uw3v6kLUK9n7Bo7sNr5u9YFiKxIF 7+5fW9QRFAe8raauQyZHZwkA+ypGmx3II7XR0Hg9/rBB5EVPPvy0+grl8WZ3ZhjW J4p5MFpF9tuLmMAaC6peewAZHnHHDEujZCL4uXcgt4Ml/gS9Hmzggh+BZwnm/APp VU4jVm1xdtrIP1mOOxtCIKgxh0BUbLdYsGm5qFymBMYZKKbY5Wm/32yeY9xkZ8V9 Tdqhacva0NAZXM2Lx91rq50dgzsk0JrjkT/I+fCievVsxwUjCJ2+X3HOCGwFcfg2 CRtIE/gs9rnJKhzbpNTWsbvcbDYO55A0sgEjUrmRWmlorkOY3vW2XLneiWKmVARf Gz7GVS8YJFkVu8jDUAQpkweTmM2FHZSdcHyyYOuB08kEAZIsOsXg8OZY/AQqqWRW XKeI2GwOOPYqdMGP/rbKGwQTQ80LaeacPLSBY1ejCJsrCHlXZgUFDfR6tA/8B+Ph cUXugBH+S+C3zP8wSDPclXXQBRayO26C2jrvoUxwqSO9XVp5wansX5KV3IihuVVO Qsfd181mNttmI4U+Oup75sCbsa7nJzye4Th35CEjBtjQfT1nMP4= =pUly -----END PGP SIGNATURE----- Merge tag 'drm-fixes-2025-02-28' of https://gitlab.freedesktop.org/drm/kernel Pull drm fixes from Dave Airlie: "This week's fixes pull, amdgpu mostly, with some xe and a few misc others, the fb defio fix is bit of a change, but it avoids some nasty NULL pointer crashes due to defio assuming page backing in places it didn't have pages. amdgpu: - Legacy dpm suspend/resume fix - Runtime PM fix for DELL G5 SE - MAINTAINERS updates - Enforce Isolation fixes - mailmap update - EDID reading i2c fix - PSR fix - eDP fix - HPD interrupt handling fix - Clear memory fix amdkfd: - MQD handling fix vkms: - fix rounding error imagination: - header fix nouveau: - connector status fix fb/defio: - NULL ptr fix for defio drivers i915: - Fix encoder HW state readout for DP UHBR MST xe: - OA uapi fix (Umesh) - Userptr related fixes - Remove a duplicated register entry - Scheduler related fix to prevent exec races when freeing it" * tag 'drm-fixes-2025-02-28' of https://gitlab.freedesktop.org/drm/kernel: (25 commits) drm/fbdev-dma: Add shadow buffering for deferred I/O drm/nouveau: Do not override forced connector status drm/i915/dp_mst: Fix encoder HW state readout for UHBR MST drm/xe: cancel pending job timer before freeing scheduler drm/xe/regs: remove a duplicate definition for RING_CTL_SIZE(size) drm/imagination: remove unnecessary header include path drm/amdgpu: init return value in amdgpu_ttm_clear_buffer drm/amd/display: Fix HPD after gpu reset drm/amd/display: add a quirk to enable eDP0 on DP1 drm/amd/display: Disable PSR-SU on eDP panels MAINTAINERS: Update AMDGPU DML maintainers info drm/amd/display: restore edid reading from a given i2c adapter mailmap: Add entry for Rodrigo Siqueira MAINTAINERS: Change my role from Maintainer to Reviewer drm/amdgpu/mes: keep enforce isolation up to date drm/amdgpu/gfx: only call mes for enforce isolation if supported MAINTAINERS: update amdgpu maintainers list drm/amdgpu: disable BAR resize on Dell G5 SE drm/amdkfd: Preserve cp_hqd_pq_control on update_mqd amdgpu/pm/legacy: fix suspend/resume issues ...
This commit is contained in:
commit
76544811c8
3
.mailmap
3
.mailmap
|
@ -522,6 +522,7 @@ Nadav Amit <nadav.amit@gmail.com> <namit@cs.technion.ac.il>
|
|||
Nadia Yvette Chambers <nyc@holomorphy.com> William Lee Irwin III <wli@holomorphy.com>
|
||||
Naoya Horiguchi <nao.horiguchi@gmail.com> <n-horiguchi@ah.jp.nec.com>
|
||||
Naoya Horiguchi <nao.horiguchi@gmail.com> <naoya.horiguchi@nec.com>
|
||||
Natalie Vock <natalie.vock@gmx.de> <friedrich.vock@gmx.de>
|
||||
Nathan Chancellor <nathan@kernel.org> <natechancellor@gmail.com>
|
||||
Naveen N Rao <naveen@kernel.org> <naveen.n.rao@linux.ibm.com>
|
||||
Naveen N Rao <naveen@kernel.org> <naveen.n.rao@linux.vnet.ibm.com>
|
||||
|
@ -613,6 +614,8 @@ Richard Leitner <richard.leitner@linux.dev> <me@g0hl1n.net>
|
|||
Richard Leitner <richard.leitner@linux.dev> <richard.leitner@skidata.com>
|
||||
Robert Foss <rfoss@kernel.org> <robert.foss@linaro.org>
|
||||
Rocky Liao <quic_rjliao@quicinc.com> <rjliao@codeaurora.org>
|
||||
Rodrigo Siqueira <siqueira@igalia.com> <rodrigosiqueiramelo@gmail.com>
|
||||
Rodrigo Siqueira <siqueira@igalia.com> <Rodrigo.Siqueira@amd.com>
|
||||
Roman Gushchin <roman.gushchin@linux.dev> <guro@fb.com>
|
||||
Roman Gushchin <roman.gushchin@linux.dev> <guroan@gmail.com>
|
||||
Roman Gushchin <roman.gushchin@linux.dev> <klamm@yandex-team.ru>
|
||||
|
|
16
MAINTAINERS
16
MAINTAINERS
|
@ -1046,14 +1046,14 @@ F: drivers/crypto/ccp/hsti.*
|
|||
AMD DISPLAY CORE
|
||||
M: Harry Wentland <harry.wentland@amd.com>
|
||||
M: Leo Li <sunpeng.li@amd.com>
|
||||
M: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
|
||||
R: Rodrigo Siqueira <siqueira@igalia.com>
|
||||
L: amd-gfx@lists.freedesktop.org
|
||||
S: Supported
|
||||
T: git https://gitlab.freedesktop.org/agd5f/linux.git
|
||||
F: drivers/gpu/drm/amd/display/
|
||||
|
||||
AMD DISPLAY CORE - DML
|
||||
M: Chaitanya Dhere <chaitanya.dhere@amd.com>
|
||||
M: Austin Zheng <austin.zheng@amd.com>
|
||||
M: Jun Lei <jun.lei@amd.com>
|
||||
S: Supported
|
||||
F: drivers/gpu/drm/amd/display/dc/dml/
|
||||
|
@ -5926,6 +5926,17 @@ F: tools/testing/selftests/cgroup/test_cpuset.c
|
|||
F: tools/testing/selftests/cgroup/test_cpuset_prs.sh
|
||||
F: tools/testing/selftests/cgroup/test_cpuset_v1_base.sh
|
||||
|
||||
CONTROL GROUP - DEVICE MEMORY CONTROLLER (DMEM)
|
||||
M: Maarten Lankhorst <dev@lankhorst.se>
|
||||
M: Maxime Ripard <mripard@kernel.org>
|
||||
M: Natalie Vock <natalie.vock@gmx.de>
|
||||
L: cgroups@vger.kernel.org
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
F: include/linux/cgroup_dmem.h
|
||||
F: kernel/cgroup/dmem.c
|
||||
|
||||
CONTROL GROUP - MEMORY RESOURCE CONTROLLER (MEMCG)
|
||||
M: Johannes Weiner <hannes@cmpxchg.org>
|
||||
M: Michal Hocko <mhocko@kernel.org>
|
||||
|
@ -19655,7 +19666,6 @@ F: drivers/net/wireless/quantenna
|
|||
RADEON and AMDGPU DRM DRIVERS
|
||||
M: Alex Deucher <alexander.deucher@amd.com>
|
||||
M: Christian König <christian.koenig@amd.com>
|
||||
M: Xinhui Pan <Xinhui.Pan@amd.com>
|
||||
L: amd-gfx@lists.freedesktop.org
|
||||
S: Supported
|
||||
B: https://gitlab.freedesktop.org/drm/amd/-/issues
|
||||
|
|
|
@ -1638,6 +1638,13 @@ int amdgpu_device_resize_fb_bar(struct amdgpu_device *adev)
|
|||
if (amdgpu_sriov_vf(adev))
|
||||
return 0;
|
||||
|
||||
/* resizing on Dell G5 SE platforms causes problems with runtime pm */
|
||||
if ((amdgpu_runtime_pm != 0) &&
|
||||
adev->pdev->vendor == PCI_VENDOR_ID_ATI &&
|
||||
adev->pdev->device == 0x731f &&
|
||||
adev->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL)
|
||||
return 0;
|
||||
|
||||
/* PCI_EXT_CAP_ID_VNDR extended capability is located at 0x100 */
|
||||
if (!pci_find_ext_capability(adev->pdev, PCI_EXT_CAP_ID_VNDR))
|
||||
DRM_WARN("System can't access extended configuration space, please check!!\n");
|
||||
|
|
|
@ -1638,22 +1638,19 @@ static ssize_t amdgpu_gfx_set_enforce_isolation(struct device *dev,
|
|||
}
|
||||
|
||||
mutex_lock(&adev->enforce_isolation_mutex);
|
||||
|
||||
for (i = 0; i < num_partitions; i++) {
|
||||
if (adev->enforce_isolation[i] && !partition_values[i]) {
|
||||
if (adev->enforce_isolation[i] && !partition_values[i])
|
||||
/* Going from enabled to disabled */
|
||||
amdgpu_vmid_free_reserved(adev, AMDGPU_GFXHUB(i));
|
||||
amdgpu_mes_set_enforce_isolation(adev, i, false);
|
||||
} else if (!adev->enforce_isolation[i] && partition_values[i]) {
|
||||
else if (!adev->enforce_isolation[i] && partition_values[i])
|
||||
/* Going from disabled to enabled */
|
||||
amdgpu_vmid_alloc_reserved(adev, AMDGPU_GFXHUB(i));
|
||||
amdgpu_mes_set_enforce_isolation(adev, i, true);
|
||||
}
|
||||
adev->enforce_isolation[i] = partition_values[i];
|
||||
}
|
||||
|
||||
mutex_unlock(&adev->enforce_isolation_mutex);
|
||||
|
||||
amdgpu_mes_update_enforce_isolation(adev);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
|
|
@ -1681,7 +1681,8 @@ bool amdgpu_mes_suspend_resume_all_supported(struct amdgpu_device *adev)
|
|||
}
|
||||
|
||||
/* Fix me -- node_id is used to identify the correct MES instances in the future */
|
||||
int amdgpu_mes_set_enforce_isolation(struct amdgpu_device *adev, uint32_t node_id, bool enable)
|
||||
static int amdgpu_mes_set_enforce_isolation(struct amdgpu_device *adev,
|
||||
uint32_t node_id, bool enable)
|
||||
{
|
||||
struct mes_misc_op_input op_input = {0};
|
||||
int r;
|
||||
|
@ -1703,6 +1704,23 @@ error:
|
|||
return r;
|
||||
}
|
||||
|
||||
int amdgpu_mes_update_enforce_isolation(struct amdgpu_device *adev)
|
||||
{
|
||||
int i, r = 0;
|
||||
|
||||
if (adev->enable_mes && adev->gfx.enable_cleaner_shader) {
|
||||
mutex_lock(&adev->enforce_isolation_mutex);
|
||||
for (i = 0; i < (adev->xcp_mgr ? adev->xcp_mgr->num_xcps : 1); i++) {
|
||||
if (adev->enforce_isolation[i])
|
||||
r |= amdgpu_mes_set_enforce_isolation(adev, i, true);
|
||||
else
|
||||
r |= amdgpu_mes_set_enforce_isolation(adev, i, false);
|
||||
}
|
||||
mutex_unlock(&adev->enforce_isolation_mutex);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
|
||||
static int amdgpu_debugfs_mes_event_log_show(struct seq_file *m, void *unused)
|
||||
|
|
|
@ -534,6 +534,6 @@ static inline void amdgpu_mes_unlock(struct amdgpu_mes *mes)
|
|||
|
||||
bool amdgpu_mes_suspend_resume_all_supported(struct amdgpu_device *adev);
|
||||
|
||||
int amdgpu_mes_set_enforce_isolation(struct amdgpu_device *adev, uint32_t node_id, bool enable);
|
||||
int amdgpu_mes_update_enforce_isolation(struct amdgpu_device *adev);
|
||||
|
||||
#endif /* __AMDGPU_MES_H__ */
|
||||
|
|
|
@ -2281,7 +2281,7 @@ int amdgpu_ttm_clear_buffer(struct amdgpu_bo *bo,
|
|||
struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring;
|
||||
struct amdgpu_res_cursor cursor;
|
||||
u64 addr;
|
||||
int r;
|
||||
int r = 0;
|
||||
|
||||
if (!adev->mman.buffer_funcs_enabled)
|
||||
return -EINVAL;
|
||||
|
|
|
@ -1633,6 +1633,10 @@ static int mes_v11_0_hw_init(struct amdgpu_ip_block *ip_block)
|
|||
goto failure;
|
||||
}
|
||||
|
||||
r = amdgpu_mes_update_enforce_isolation(adev);
|
||||
if (r)
|
||||
goto failure;
|
||||
|
||||
out:
|
||||
/*
|
||||
* Disable KIQ ring usage from the driver once MES is enabled.
|
||||
|
|
|
@ -1743,6 +1743,10 @@ static int mes_v12_0_hw_init(struct amdgpu_ip_block *ip_block)
|
|||
goto failure;
|
||||
}
|
||||
|
||||
r = amdgpu_mes_update_enforce_isolation(adev);
|
||||
if (r)
|
||||
goto failure;
|
||||
|
||||
out:
|
||||
/*
|
||||
* Disable KIQ ring usage from the driver once MES is enabled.
|
||||
|
|
|
@ -107,6 +107,8 @@ static void init_mqd(struct mqd_manager *mm, void **mqd,
|
|||
m->cp_hqd_persistent_state = CP_HQD_PERSISTENT_STATE__PRELOAD_REQ_MASK |
|
||||
0x53 << CP_HQD_PERSISTENT_STATE__PRELOAD_SIZE__SHIFT;
|
||||
|
||||
m->cp_hqd_pq_control = 5 << CP_HQD_PQ_CONTROL__RPTR_BLOCK_SIZE__SHIFT;
|
||||
m->cp_hqd_pq_control |= CP_HQD_PQ_CONTROL__UNORD_DISPATCH_MASK;
|
||||
m->cp_mqd_control = 1 << CP_MQD_CONTROL__PRIV_STATE__SHIFT;
|
||||
|
||||
m->cp_mqd_base_addr_lo = lower_32_bits(addr);
|
||||
|
@ -167,10 +169,10 @@ static void update_mqd(struct mqd_manager *mm, void *mqd,
|
|||
|
||||
m = get_mqd(mqd);
|
||||
|
||||
m->cp_hqd_pq_control = 5 << CP_HQD_PQ_CONTROL__RPTR_BLOCK_SIZE__SHIFT;
|
||||
m->cp_hqd_pq_control &= ~CP_HQD_PQ_CONTROL__QUEUE_SIZE_MASK;
|
||||
m->cp_hqd_pq_control |=
|
||||
ffs(q->queue_size / sizeof(unsigned int)) - 1 - 1;
|
||||
m->cp_hqd_pq_control |= CP_HQD_PQ_CONTROL__UNORD_DISPATCH_MASK;
|
||||
|
||||
pr_debug("cp_hqd_pq_control 0x%x\n", m->cp_hqd_pq_control);
|
||||
|
||||
m->cp_hqd_pq_base_lo = lower_32_bits((uint64_t)q->queue_address >> 8);
|
||||
|
|
|
@ -154,6 +154,8 @@ static void init_mqd(struct mqd_manager *mm, void **mqd,
|
|||
m->cp_hqd_persistent_state = CP_HQD_PERSISTENT_STATE__PRELOAD_REQ_MASK |
|
||||
0x55 << CP_HQD_PERSISTENT_STATE__PRELOAD_SIZE__SHIFT;
|
||||
|
||||
m->cp_hqd_pq_control = 5 << CP_HQD_PQ_CONTROL__RPTR_BLOCK_SIZE__SHIFT;
|
||||
m->cp_hqd_pq_control |= CP_HQD_PQ_CONTROL__UNORD_DISPATCH_MASK;
|
||||
m->cp_mqd_control = 1 << CP_MQD_CONTROL__PRIV_STATE__SHIFT;
|
||||
|
||||
m->cp_mqd_base_addr_lo = lower_32_bits(addr);
|
||||
|
@ -221,10 +223,9 @@ static void update_mqd(struct mqd_manager *mm, void *mqd,
|
|||
|
||||
m = get_mqd(mqd);
|
||||
|
||||
m->cp_hqd_pq_control = 5 << CP_HQD_PQ_CONTROL__RPTR_BLOCK_SIZE__SHIFT;
|
||||
m->cp_hqd_pq_control &= ~CP_HQD_PQ_CONTROL__QUEUE_SIZE_MASK;
|
||||
m->cp_hqd_pq_control |=
|
||||
ffs(q->queue_size / sizeof(unsigned int)) - 1 - 1;
|
||||
m->cp_hqd_pq_control |= CP_HQD_PQ_CONTROL__UNORD_DISPATCH_MASK;
|
||||
pr_debug("cp_hqd_pq_control 0x%x\n", m->cp_hqd_pq_control);
|
||||
|
||||
m->cp_hqd_pq_base_lo = lower_32_bits((uint64_t)q->queue_address >> 8);
|
||||
|
|
|
@ -121,6 +121,8 @@ static void init_mqd(struct mqd_manager *mm, void **mqd,
|
|||
m->cp_hqd_persistent_state = CP_HQD_PERSISTENT_STATE__PRELOAD_REQ_MASK |
|
||||
0x55 << CP_HQD_PERSISTENT_STATE__PRELOAD_SIZE__SHIFT;
|
||||
|
||||
m->cp_hqd_pq_control = 5 << CP_HQD_PQ_CONTROL__RPTR_BLOCK_SIZE__SHIFT;
|
||||
m->cp_hqd_pq_control |= CP_HQD_PQ_CONTROL__UNORD_DISPATCH_MASK;
|
||||
m->cp_mqd_control = 1 << CP_MQD_CONTROL__PRIV_STATE__SHIFT;
|
||||
|
||||
m->cp_mqd_base_addr_lo = lower_32_bits(addr);
|
||||
|
@ -184,10 +186,9 @@ static void update_mqd(struct mqd_manager *mm, void *mqd,
|
|||
|
||||
m = get_mqd(mqd);
|
||||
|
||||
m->cp_hqd_pq_control = 5 << CP_HQD_PQ_CONTROL__RPTR_BLOCK_SIZE__SHIFT;
|
||||
m->cp_hqd_pq_control &= ~CP_HQD_PQ_CONTROL__QUEUE_SIZE_MASK;
|
||||
m->cp_hqd_pq_control |=
|
||||
ffs(q->queue_size / sizeof(unsigned int)) - 1 - 1;
|
||||
m->cp_hqd_pq_control |= CP_HQD_PQ_CONTROL__UNORD_DISPATCH_MASK;
|
||||
pr_debug("cp_hqd_pq_control 0x%x\n", m->cp_hqd_pq_control);
|
||||
|
||||
m->cp_hqd_pq_base_lo = lower_32_bits((uint64_t)q->queue_address >> 8);
|
||||
|
|
|
@ -183,6 +183,9 @@ static void init_mqd(struct mqd_manager *mm, void **mqd,
|
|||
m->cp_hqd_persistent_state = CP_HQD_PERSISTENT_STATE__PRELOAD_REQ_MASK |
|
||||
0x53 << CP_HQD_PERSISTENT_STATE__PRELOAD_SIZE__SHIFT;
|
||||
|
||||
m->cp_hqd_pq_control = 5 << CP_HQD_PQ_CONTROL__RPTR_BLOCK_SIZE__SHIFT;
|
||||
m->cp_hqd_pq_control |= CP_HQD_PQ_CONTROL__UNORD_DISPATCH_MASK;
|
||||
|
||||
m->cp_mqd_control = 1 << CP_MQD_CONTROL__PRIV_STATE__SHIFT;
|
||||
|
||||
m->cp_mqd_base_addr_lo = lower_32_bits(addr);
|
||||
|
@ -245,7 +248,7 @@ static void update_mqd(struct mqd_manager *mm, void *mqd,
|
|||
|
||||
m = get_mqd(mqd);
|
||||
|
||||
m->cp_hqd_pq_control = 5 << CP_HQD_PQ_CONTROL__RPTR_BLOCK_SIZE__SHIFT;
|
||||
m->cp_hqd_pq_control &= ~CP_HQD_PQ_CONTROL__QUEUE_SIZE_MASK;
|
||||
m->cp_hqd_pq_control |= order_base_2(q->queue_size / 4) - 1;
|
||||
pr_debug("cp_hqd_pq_control 0x%x\n", m->cp_hqd_pq_control);
|
||||
|
||||
|
|
|
@ -1618,75 +1618,130 @@ static bool dm_should_disable_stutter(struct pci_dev *pdev)
|
|||
return false;
|
||||
}
|
||||
|
||||
static const struct dmi_system_id hpd_disconnect_quirk_table[] = {
|
||||
struct amdgpu_dm_quirks {
|
||||
bool aux_hpd_discon;
|
||||
bool support_edp0_on_dp1;
|
||||
};
|
||||
|
||||
static struct amdgpu_dm_quirks quirk_entries = {
|
||||
.aux_hpd_discon = false,
|
||||
.support_edp0_on_dp1 = false
|
||||
};
|
||||
|
||||
static int edp0_on_dp1_callback(const struct dmi_system_id *id)
|
||||
{
|
||||
quirk_entries.support_edp0_on_dp1 = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aux_hpd_discon_callback(const struct dmi_system_id *id)
|
||||
{
|
||||
quirk_entries.aux_hpd_discon = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dmi_system_id dmi_quirk_table[] = {
|
||||
{
|
||||
.callback = aux_hpd_discon_callback,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Precision 3660"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = aux_hpd_discon_callback,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Precision 3260"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = aux_hpd_discon_callback,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Precision 3460"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = aux_hpd_discon_callback,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex Tower Plus 7010"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = aux_hpd_discon_callback,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex Tower 7010"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = aux_hpd_discon_callback,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex SFF Plus 7010"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = aux_hpd_discon_callback,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex SFF 7010"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = aux_hpd_discon_callback,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex Micro Plus 7010"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = aux_hpd_discon_callback,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex Micro 7010"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = edp0_on_dp1_callback,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "HP"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "HP Elite mt645 G8 Mobile Thin Client"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = edp0_on_dp1_callback,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "HP"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook 665 16 inch G11 Notebook PC"),
|
||||
},
|
||||
},
|
||||
{}
|
||||
/* TODO: refactor this from a fixed table to a dynamic option */
|
||||
};
|
||||
|
||||
static void retrieve_dmi_info(struct amdgpu_display_manager *dm)
|
||||
static void retrieve_dmi_info(struct amdgpu_display_manager *dm, struct dc_init_data *init_data)
|
||||
{
|
||||
const struct dmi_system_id *dmi_id;
|
||||
int dmi_id;
|
||||
struct drm_device *dev = dm->ddev;
|
||||
|
||||
dm->aux_hpd_discon_quirk = false;
|
||||
init_data->flags.support_edp0_on_dp1 = false;
|
||||
|
||||
dmi_id = dmi_first_match(hpd_disconnect_quirk_table);
|
||||
if (dmi_id) {
|
||||
dmi_id = dmi_check_system(dmi_quirk_table);
|
||||
|
||||
if (!dmi_id)
|
||||
return;
|
||||
|
||||
if (quirk_entries.aux_hpd_discon) {
|
||||
dm->aux_hpd_discon_quirk = true;
|
||||
DRM_INFO("aux_hpd_discon_quirk attached\n");
|
||||
drm_info(dev, "aux_hpd_discon_quirk attached\n");
|
||||
}
|
||||
if (quirk_entries.support_edp0_on_dp1) {
|
||||
init_data->flags.support_edp0_on_dp1 = true;
|
||||
drm_info(dev, "aux_hpd_discon_quirk attached\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1994,7 +2049,7 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
|
|||
if (amdgpu_ip_version(adev, DCE_HWIP, 0) >= IP_VERSION(3, 0, 0))
|
||||
init_data.num_virtual_links = 1;
|
||||
|
||||
retrieve_dmi_info(&adev->dm);
|
||||
retrieve_dmi_info(&adev->dm, &init_data);
|
||||
|
||||
if (adev->dm.bb_from_dmub)
|
||||
init_data.bb_from_dmub = adev->dm.bb_from_dmub;
|
||||
|
@ -7240,8 +7295,14 @@ static void amdgpu_dm_connector_funcs_force(struct drm_connector *connector)
|
|||
struct dc_link *dc_link = aconnector->dc_link;
|
||||
struct dc_sink *dc_em_sink = aconnector->dc_em_sink;
|
||||
const struct drm_edid *drm_edid;
|
||||
struct i2c_adapter *ddc;
|
||||
|
||||
drm_edid = drm_edid_read(connector);
|
||||
if (dc_link && dc_link->aux_mode)
|
||||
ddc = &aconnector->dm_dp_aux.aux.ddc;
|
||||
else
|
||||
ddc = &aconnector->i2c->base;
|
||||
|
||||
drm_edid = drm_edid_read_ddc(connector, ddc);
|
||||
drm_edid_connector_update(connector, drm_edid);
|
||||
if (!drm_edid) {
|
||||
DRM_ERROR("No EDID found on connector: %s.\n", connector->name);
|
||||
|
@ -7286,14 +7347,21 @@ static int get_modes(struct drm_connector *connector)
|
|||
static void create_eml_sink(struct amdgpu_dm_connector *aconnector)
|
||||
{
|
||||
struct drm_connector *connector = &aconnector->base;
|
||||
struct dc_link *dc_link = aconnector->dc_link;
|
||||
struct dc_sink_init_data init_params = {
|
||||
.link = aconnector->dc_link,
|
||||
.sink_signal = SIGNAL_TYPE_VIRTUAL
|
||||
};
|
||||
const struct drm_edid *drm_edid;
|
||||
const struct edid *edid;
|
||||
struct i2c_adapter *ddc;
|
||||
|
||||
drm_edid = drm_edid_read(connector);
|
||||
if (dc_link && dc_link->aux_mode)
|
||||
ddc = &aconnector->dm_dp_aux.aux.ddc;
|
||||
else
|
||||
ddc = &aconnector->i2c->base;
|
||||
|
||||
drm_edid = drm_edid_read_ddc(connector, ddc);
|
||||
drm_edid_connector_update(connector, drm_edid);
|
||||
if (!drm_edid) {
|
||||
DRM_ERROR("No EDID found on connector: %s.\n", connector->name);
|
||||
|
|
|
@ -894,6 +894,7 @@ void amdgpu_dm_hpd_init(struct amdgpu_device *adev)
|
|||
struct drm_device *dev = adev_to_drm(adev);
|
||||
struct drm_connector *connector;
|
||||
struct drm_connector_list_iter iter;
|
||||
int i;
|
||||
|
||||
drm_connector_list_iter_begin(dev, &iter);
|
||||
drm_for_each_connector_iter(connector, &iter) {
|
||||
|
@ -920,6 +921,12 @@ void amdgpu_dm_hpd_init(struct amdgpu_device *adev)
|
|||
}
|
||||
}
|
||||
drm_connector_list_iter_end(&iter);
|
||||
|
||||
/* Update reference counts for HPDs */
|
||||
for (i = DC_IRQ_SOURCE_HPD1; i <= adev->mode_info.num_hpd; i++) {
|
||||
if (amdgpu_irq_get(adev, &adev->hpd_irq, i - DC_IRQ_SOURCE_HPD1))
|
||||
drm_err(dev, "DM_IRQ: Failed get HPD for source=%d)!\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -935,6 +942,7 @@ void amdgpu_dm_hpd_fini(struct amdgpu_device *adev)
|
|||
struct drm_device *dev = adev_to_drm(adev);
|
||||
struct drm_connector *connector;
|
||||
struct drm_connector_list_iter iter;
|
||||
int i;
|
||||
|
||||
drm_connector_list_iter_begin(dev, &iter);
|
||||
drm_for_each_connector_iter(connector, &iter) {
|
||||
|
@ -960,4 +968,10 @@ void amdgpu_dm_hpd_fini(struct amdgpu_device *adev)
|
|||
}
|
||||
}
|
||||
drm_connector_list_iter_end(&iter);
|
||||
|
||||
/* Update reference counts for HPDs */
|
||||
for (i = DC_IRQ_SOURCE_HPD1; i <= adev->mode_info.num_hpd; i++) {
|
||||
if (amdgpu_irq_put(adev, &adev->hpd_irq, i - DC_IRQ_SOURCE_HPD1))
|
||||
drm_err(dev, "DM_IRQ: Failed put HPD for source=%d!\n", i);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,7 +54,8 @@ static bool link_supports_psrsu(struct dc_link *link)
|
|||
if (amdgpu_dc_debug_mask & DC_DISABLE_PSR_SU)
|
||||
return false;
|
||||
|
||||
return dc_dmub_check_min_version(dc->ctx->dmub_srv->dmub);
|
||||
/* Temporarily disable PSR-SU to avoid glitches */
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -3042,6 +3042,7 @@ static int kv_dpm_hw_init(struct amdgpu_ip_block *ip_block)
|
|||
if (!amdgpu_dpm)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&adev->pm.mutex);
|
||||
kv_dpm_setup_asic(adev);
|
||||
ret = kv_dpm_enable(adev);
|
||||
if (ret)
|
||||
|
@ -3049,6 +3050,8 @@ static int kv_dpm_hw_init(struct amdgpu_ip_block *ip_block)
|
|||
else
|
||||
adev->pm.dpm_enabled = true;
|
||||
amdgpu_legacy_dpm_compute_clocks(adev);
|
||||
mutex_unlock(&adev->pm.mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -3066,32 +3069,42 @@ static int kv_dpm_suspend(struct amdgpu_ip_block *ip_block)
|
|||
{
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
|
||||
cancel_work_sync(&adev->pm.dpm.thermal.work);
|
||||
|
||||
if (adev->pm.dpm_enabled) {
|
||||
mutex_lock(&adev->pm.mutex);
|
||||
adev->pm.dpm_enabled = false;
|
||||
/* disable dpm */
|
||||
kv_dpm_disable(adev);
|
||||
/* reset the power state */
|
||||
adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps = adev->pm.dpm.boot_ps;
|
||||
mutex_unlock(&adev->pm.mutex);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kv_dpm_resume(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
int ret;
|
||||
int ret = 0;
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
|
||||
if (adev->pm.dpm_enabled) {
|
||||
if (!amdgpu_dpm)
|
||||
return 0;
|
||||
|
||||
if (!adev->pm.dpm_enabled) {
|
||||
mutex_lock(&adev->pm.mutex);
|
||||
/* asic init will reset to the boot state */
|
||||
kv_dpm_setup_asic(adev);
|
||||
ret = kv_dpm_enable(adev);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
adev->pm.dpm_enabled = false;
|
||||
else
|
||||
} else {
|
||||
adev->pm.dpm_enabled = true;
|
||||
if (adev->pm.dpm_enabled)
|
||||
amdgpu_legacy_dpm_compute_clocks(adev);
|
||||
}
|
||||
mutex_unlock(&adev->pm.mutex);
|
||||
}
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool kv_dpm_is_idle(void *handle)
|
||||
|
|
|
@ -1009,9 +1009,12 @@ void amdgpu_dpm_thermal_work_handler(struct work_struct *work)
|
|||
enum amd_pm_state_type dpm_state = POWER_STATE_TYPE_INTERNAL_THERMAL;
|
||||
int temp, size = sizeof(temp);
|
||||
|
||||
if (!adev->pm.dpm_enabled)
|
||||
return;
|
||||
mutex_lock(&adev->pm.mutex);
|
||||
|
||||
if (!adev->pm.dpm_enabled) {
|
||||
mutex_unlock(&adev->pm.mutex);
|
||||
return;
|
||||
}
|
||||
if (!pp_funcs->read_sensor(adev->powerplay.pp_handle,
|
||||
AMDGPU_PP_SENSOR_GPU_TEMP,
|
||||
(void *)&temp,
|
||||
|
@ -1033,4 +1036,5 @@ void amdgpu_dpm_thermal_work_handler(struct work_struct *work)
|
|||
adev->pm.dpm.state = dpm_state;
|
||||
|
||||
amdgpu_legacy_dpm_compute_clocks(adev->powerplay.pp_handle);
|
||||
mutex_unlock(&adev->pm.mutex);
|
||||
}
|
||||
|
|
|
@ -7786,6 +7786,7 @@ static int si_dpm_hw_init(struct amdgpu_ip_block *ip_block)
|
|||
if (!amdgpu_dpm)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&adev->pm.mutex);
|
||||
si_dpm_setup_asic(adev);
|
||||
ret = si_dpm_enable(adev);
|
||||
if (ret)
|
||||
|
@ -7793,6 +7794,7 @@ static int si_dpm_hw_init(struct amdgpu_ip_block *ip_block)
|
|||
else
|
||||
adev->pm.dpm_enabled = true;
|
||||
amdgpu_legacy_dpm_compute_clocks(adev);
|
||||
mutex_unlock(&adev->pm.mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -7810,32 +7812,44 @@ static int si_dpm_suspend(struct amdgpu_ip_block *ip_block)
|
|||
{
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
|
||||
cancel_work_sync(&adev->pm.dpm.thermal.work);
|
||||
|
||||
if (adev->pm.dpm_enabled) {
|
||||
mutex_lock(&adev->pm.mutex);
|
||||
adev->pm.dpm_enabled = false;
|
||||
/* disable dpm */
|
||||
si_dpm_disable(adev);
|
||||
/* reset the power state */
|
||||
adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps = adev->pm.dpm.boot_ps;
|
||||
mutex_unlock(&adev->pm.mutex);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int si_dpm_resume(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
int ret;
|
||||
int ret = 0;
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
|
||||
if (adev->pm.dpm_enabled) {
|
||||
if (!amdgpu_dpm)
|
||||
return 0;
|
||||
|
||||
if (!adev->pm.dpm_enabled) {
|
||||
/* asic init will reset to the boot state */
|
||||
mutex_lock(&adev->pm.mutex);
|
||||
si_dpm_setup_asic(adev);
|
||||
ret = si_dpm_enable(adev);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
adev->pm.dpm_enabled = false;
|
||||
else
|
||||
} else {
|
||||
adev->pm.dpm_enabled = true;
|
||||
if (adev->pm.dpm_enabled)
|
||||
amdgpu_legacy_dpm_compute_clocks(adev);
|
||||
}
|
||||
mutex_unlock(&adev->pm.mutex);
|
||||
}
|
||||
return 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool si_dpm_is_idle(void *handle)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <linux/fb.h>
|
||||
#include <linux/vmalloc.h>
|
||||
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_fbdev_dma.h>
|
||||
|
@ -70,37 +71,102 @@ static const struct fb_ops drm_fbdev_dma_fb_ops = {
|
|||
.fb_destroy = drm_fbdev_dma_fb_destroy,
|
||||
};
|
||||
|
||||
FB_GEN_DEFAULT_DEFERRED_DMAMEM_OPS(drm_fbdev_dma,
|
||||
FB_GEN_DEFAULT_DEFERRED_DMAMEM_OPS(drm_fbdev_dma_shadowed,
|
||||
drm_fb_helper_damage_range,
|
||||
drm_fb_helper_damage_area);
|
||||
|
||||
static int drm_fbdev_dma_deferred_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
|
||||
static void drm_fbdev_dma_shadowed_fb_destroy(struct fb_info *info)
|
||||
{
|
||||
struct drm_fb_helper *fb_helper = info->par;
|
||||
struct drm_framebuffer *fb = fb_helper->fb;
|
||||
struct drm_gem_dma_object *dma = drm_fb_dma_get_gem_obj(fb, 0);
|
||||
void *shadow = info->screen_buffer;
|
||||
|
||||
if (!dma->map_noncoherent)
|
||||
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
|
||||
if (!fb_helper->dev)
|
||||
return;
|
||||
|
||||
return fb_deferred_io_mmap(info, vma);
|
||||
if (info->fbdefio)
|
||||
fb_deferred_io_cleanup(info);
|
||||
drm_fb_helper_fini(fb_helper);
|
||||
vfree(shadow);
|
||||
|
||||
drm_client_buffer_vunmap(fb_helper->buffer);
|
||||
drm_client_framebuffer_delete(fb_helper->buffer);
|
||||
drm_client_release(&fb_helper->client);
|
||||
drm_fb_helper_unprepare(fb_helper);
|
||||
kfree(fb_helper);
|
||||
}
|
||||
|
||||
static const struct fb_ops drm_fbdev_dma_deferred_fb_ops = {
|
||||
static const struct fb_ops drm_fbdev_dma_shadowed_fb_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.fb_open = drm_fbdev_dma_fb_open,
|
||||
.fb_release = drm_fbdev_dma_fb_release,
|
||||
__FB_DEFAULT_DEFERRED_OPS_RDWR(drm_fbdev_dma),
|
||||
FB_DEFAULT_DEFERRED_OPS(drm_fbdev_dma_shadowed),
|
||||
DRM_FB_HELPER_DEFAULT_OPS,
|
||||
__FB_DEFAULT_DEFERRED_OPS_DRAW(drm_fbdev_dma),
|
||||
.fb_mmap = drm_fbdev_dma_deferred_fb_mmap,
|
||||
.fb_destroy = drm_fbdev_dma_fb_destroy,
|
||||
.fb_destroy = drm_fbdev_dma_shadowed_fb_destroy,
|
||||
};
|
||||
|
||||
/*
|
||||
* struct drm_fb_helper
|
||||
*/
|
||||
|
||||
static void drm_fbdev_dma_damage_blit_real(struct drm_fb_helper *fb_helper,
|
||||
struct drm_clip_rect *clip,
|
||||
struct iosys_map *dst)
|
||||
{
|
||||
struct drm_framebuffer *fb = fb_helper->fb;
|
||||
size_t offset = clip->y1 * fb->pitches[0];
|
||||
size_t len = clip->x2 - clip->x1;
|
||||
unsigned int y;
|
||||
void *src;
|
||||
|
||||
switch (drm_format_info_bpp(fb->format, 0)) {
|
||||
case 1:
|
||||
offset += clip->x1 / 8;
|
||||
len = DIV_ROUND_UP(len + clip->x1 % 8, 8);
|
||||
break;
|
||||
case 2:
|
||||
offset += clip->x1 / 4;
|
||||
len = DIV_ROUND_UP(len + clip->x1 % 4, 4);
|
||||
break;
|
||||
case 4:
|
||||
offset += clip->x1 / 2;
|
||||
len = DIV_ROUND_UP(len + clip->x1 % 2, 2);
|
||||
break;
|
||||
default:
|
||||
offset += clip->x1 * fb->format->cpp[0];
|
||||
len *= fb->format->cpp[0];
|
||||
break;
|
||||
}
|
||||
|
||||
src = fb_helper->info->screen_buffer + offset;
|
||||
iosys_map_incr(dst, offset); /* go to first pixel within clip rect */
|
||||
|
||||
for (y = clip->y1; y < clip->y2; y++) {
|
||||
iosys_map_memcpy_to(dst, 0, src, len);
|
||||
iosys_map_incr(dst, fb->pitches[0]);
|
||||
src += fb->pitches[0];
|
||||
}
|
||||
}
|
||||
|
||||
static int drm_fbdev_dma_damage_blit(struct drm_fb_helper *fb_helper,
|
||||
struct drm_clip_rect *clip)
|
||||
{
|
||||
struct drm_client_buffer *buffer = fb_helper->buffer;
|
||||
struct iosys_map dst;
|
||||
|
||||
/*
|
||||
* For fbdev emulation, we only have to protect against fbdev modeset
|
||||
* operations. Nothing else will involve the client buffer's BO. So it
|
||||
* is sufficient to acquire struct drm_fb_helper.lock here.
|
||||
*/
|
||||
mutex_lock(&fb_helper->lock);
|
||||
|
||||
dst = buffer->map;
|
||||
drm_fbdev_dma_damage_blit_real(fb_helper, clip, &dst);
|
||||
|
||||
mutex_unlock(&fb_helper->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int drm_fbdev_dma_helper_fb_dirty(struct drm_fb_helper *helper,
|
||||
struct drm_clip_rect *clip)
|
||||
{
|
||||
|
@ -112,6 +178,10 @@ static int drm_fbdev_dma_helper_fb_dirty(struct drm_fb_helper *helper,
|
|||
return 0;
|
||||
|
||||
if (helper->fb->funcs->dirty) {
|
||||
ret = drm_fbdev_dma_damage_blit(helper, clip);
|
||||
if (drm_WARN_ONCE(dev, ret, "Damage blitter failed: ret=%d\n", ret))
|
||||
return ret;
|
||||
|
||||
ret = helper->fb->funcs->dirty(helper->fb, NULL, 0, 0, clip, 1);
|
||||
if (drm_WARN_ONCE(dev, ret, "Dirty helper failed: ret=%d\n", ret))
|
||||
return ret;
|
||||
|
@ -128,14 +198,80 @@ static const struct drm_fb_helper_funcs drm_fbdev_dma_helper_funcs = {
|
|||
* struct drm_fb_helper
|
||||
*/
|
||||
|
||||
static int drm_fbdev_dma_driver_fbdev_probe_tail(struct drm_fb_helper *fb_helper,
|
||||
struct drm_fb_helper_surface_size *sizes)
|
||||
{
|
||||
struct drm_device *dev = fb_helper->dev;
|
||||
struct drm_client_buffer *buffer = fb_helper->buffer;
|
||||
struct drm_gem_dma_object *dma_obj = to_drm_gem_dma_obj(buffer->gem);
|
||||
struct drm_framebuffer *fb = fb_helper->fb;
|
||||
struct fb_info *info = fb_helper->info;
|
||||
struct iosys_map map = buffer->map;
|
||||
|
||||
info->fbops = &drm_fbdev_dma_fb_ops;
|
||||
|
||||
/* screen */
|
||||
info->flags |= FBINFO_VIRTFB; /* system memory */
|
||||
if (dma_obj->map_noncoherent)
|
||||
info->flags |= FBINFO_READS_FAST; /* signal caching */
|
||||
info->screen_size = sizes->surface_height * fb->pitches[0];
|
||||
info->screen_buffer = map.vaddr;
|
||||
if (!(info->flags & FBINFO_HIDE_SMEM_START)) {
|
||||
if (!drm_WARN_ON(dev, is_vmalloc_addr(info->screen_buffer)))
|
||||
info->fix.smem_start = page_to_phys(virt_to_page(info->screen_buffer));
|
||||
}
|
||||
info->fix.smem_len = info->screen_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int drm_fbdev_dma_driver_fbdev_probe_tail_shadowed(struct drm_fb_helper *fb_helper,
|
||||
struct drm_fb_helper_surface_size *sizes)
|
||||
{
|
||||
struct drm_client_buffer *buffer = fb_helper->buffer;
|
||||
struct fb_info *info = fb_helper->info;
|
||||
size_t screen_size = buffer->gem->size;
|
||||
void *screen_buffer;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Deferred I/O requires struct page for framebuffer memory,
|
||||
* which is not guaranteed for all DMA ranges. We thus create
|
||||
* a shadow buffer in system memory.
|
||||
*/
|
||||
screen_buffer = vzalloc(screen_size);
|
||||
if (!screen_buffer)
|
||||
return -ENOMEM;
|
||||
|
||||
info->fbops = &drm_fbdev_dma_shadowed_fb_ops;
|
||||
|
||||
/* screen */
|
||||
info->flags |= FBINFO_VIRTFB; /* system memory */
|
||||
info->flags |= FBINFO_READS_FAST; /* signal caching */
|
||||
info->screen_buffer = screen_buffer;
|
||||
info->fix.smem_len = screen_size;
|
||||
|
||||
fb_helper->fbdefio.delay = HZ / 20;
|
||||
fb_helper->fbdefio.deferred_io = drm_fb_helper_deferred_io;
|
||||
|
||||
info->fbdefio = &fb_helper->fbdefio;
|
||||
ret = fb_deferred_io_init(info);
|
||||
if (ret)
|
||||
goto err_vfree;
|
||||
|
||||
return 0;
|
||||
|
||||
err_vfree:
|
||||
vfree(screen_buffer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int drm_fbdev_dma_driver_fbdev_probe(struct drm_fb_helper *fb_helper,
|
||||
struct drm_fb_helper_surface_size *sizes)
|
||||
{
|
||||
struct drm_client_dev *client = &fb_helper->client;
|
||||
struct drm_device *dev = fb_helper->dev;
|
||||
bool use_deferred_io = false;
|
||||
struct drm_client_buffer *buffer;
|
||||
struct drm_gem_dma_object *dma_obj;
|
||||
struct drm_framebuffer *fb;
|
||||
struct fb_info *info;
|
||||
u32 format;
|
||||
|
@ -152,19 +288,9 @@ int drm_fbdev_dma_driver_fbdev_probe(struct drm_fb_helper *fb_helper,
|
|||
sizes->surface_height, format);
|
||||
if (IS_ERR(buffer))
|
||||
return PTR_ERR(buffer);
|
||||
dma_obj = to_drm_gem_dma_obj(buffer->gem);
|
||||
|
||||
fb = buffer->fb;
|
||||
|
||||
/*
|
||||
* Deferred I/O requires struct page for framebuffer memory,
|
||||
* which is not guaranteed for all DMA ranges. We thus only
|
||||
* install deferred I/O if we have a framebuffer that requires
|
||||
* it.
|
||||
*/
|
||||
if (fb->funcs->dirty)
|
||||
use_deferred_io = true;
|
||||
|
||||
ret = drm_client_buffer_vmap(buffer, &map);
|
||||
if (ret) {
|
||||
goto err_drm_client_buffer_delete;
|
||||
|
@ -185,45 +311,12 @@ int drm_fbdev_dma_driver_fbdev_probe(struct drm_fb_helper *fb_helper,
|
|||
|
||||
drm_fb_helper_fill_info(info, fb_helper, sizes);
|
||||
|
||||
if (use_deferred_io)
|
||||
info->fbops = &drm_fbdev_dma_deferred_fb_ops;
|
||||
if (fb->funcs->dirty)
|
||||
ret = drm_fbdev_dma_driver_fbdev_probe_tail_shadowed(fb_helper, sizes);
|
||||
else
|
||||
info->fbops = &drm_fbdev_dma_fb_ops;
|
||||
|
||||
/* screen */
|
||||
info->flags |= FBINFO_VIRTFB; /* system memory */
|
||||
if (dma_obj->map_noncoherent)
|
||||
info->flags |= FBINFO_READS_FAST; /* signal caching */
|
||||
info->screen_size = sizes->surface_height * fb->pitches[0];
|
||||
info->screen_buffer = map.vaddr;
|
||||
if (!(info->flags & FBINFO_HIDE_SMEM_START)) {
|
||||
if (!drm_WARN_ON(dev, is_vmalloc_addr(info->screen_buffer)))
|
||||
info->fix.smem_start = page_to_phys(virt_to_page(info->screen_buffer));
|
||||
}
|
||||
info->fix.smem_len = info->screen_size;
|
||||
|
||||
/*
|
||||
* Only set up deferred I/O if the screen buffer supports
|
||||
* it. If this disagrees with the previous test for ->dirty,
|
||||
* mmap on the /dev/fb file might not work correctly.
|
||||
*/
|
||||
if (!is_vmalloc_addr(info->screen_buffer) && info->fix.smem_start) {
|
||||
unsigned long pfn = info->fix.smem_start >> PAGE_SHIFT;
|
||||
|
||||
if (drm_WARN_ON(dev, !pfn_to_page(pfn)))
|
||||
use_deferred_io = false;
|
||||
}
|
||||
|
||||
/* deferred I/O */
|
||||
if (use_deferred_io) {
|
||||
fb_helper->fbdefio.delay = HZ / 20;
|
||||
fb_helper->fbdefio.deferred_io = drm_fb_helper_deferred_io;
|
||||
|
||||
info->fbdefio = &fb_helper->fbdefio;
|
||||
ret = fb_deferred_io_init(info);
|
||||
if (ret)
|
||||
goto err_drm_fb_helper_release_info;
|
||||
}
|
||||
ret = drm_fbdev_dma_driver_fbdev_probe_tail(fb_helper, sizes);
|
||||
if (ret)
|
||||
goto err_drm_fb_helper_release_info;
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -866,7 +866,7 @@ static void intel_ddi_get_encoder_pipes(struct intel_encoder *encoder,
|
|||
encoder->base.base.id, encoder->base.name);
|
||||
|
||||
if (!mst_pipe_mask && dp128b132b_pipe_mask) {
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
|
||||
|
||||
/*
|
||||
* If we don't have 8b/10b MST, but have more than one
|
||||
|
@ -878,7 +878,8 @@ static void intel_ddi_get_encoder_pipes(struct intel_encoder *encoder,
|
|||
* we don't expect MST to have been enabled at that point, and
|
||||
* can assume it's SST.
|
||||
*/
|
||||
if (hweight8(dp128b132b_pipe_mask) > 1 || intel_dp->is_mst)
|
||||
if (hweight8(dp128b132b_pipe_mask) > 1 ||
|
||||
intel_dp_mst_encoder_active_links(dig_port))
|
||||
mst_pipe_mask = dp128b132b_pipe_mask;
|
||||
}
|
||||
|
||||
|
@ -4151,13 +4152,13 @@ static void intel_ddi_read_func_ctl(struct intel_encoder *encoder,
|
|||
} else if (ddi_mode == TRANS_DDI_MODE_SELECT_DP_MST) {
|
||||
intel_ddi_read_func_ctl_dp_mst(encoder, pipe_config, ddi_func_ctl);
|
||||
} else if (ddi_mode == TRANS_DDI_MODE_SELECT_FDI_OR_128B132B && HAS_DP20(display)) {
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
|
||||
|
||||
/*
|
||||
* If this is true, we know we're being called from mst stream
|
||||
* encoder's ->get_config().
|
||||
*/
|
||||
if (intel_dp->is_mst)
|
||||
if (intel_dp_mst_encoder_active_links(dig_port))
|
||||
intel_ddi_read_func_ctl_dp_mst(encoder, pipe_config, ddi_func_ctl);
|
||||
else
|
||||
intel_ddi_read_func_ctl_dp_sst(encoder, pipe_config, ddi_func_ctl);
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR MIT
|
||||
# Copyright (c) 2023 Imagination Technologies Ltd.
|
||||
|
||||
subdir-ccflags-y := -I$(src)
|
||||
|
||||
powervr-y := \
|
||||
pvr_ccb.o \
|
||||
pvr_cccb.o \
|
||||
|
|
|
@ -775,7 +775,6 @@ nouveau_connector_force(struct drm_connector *connector)
|
|||
if (!nv_encoder) {
|
||||
NV_ERROR(drm, "can't find encoder to force %s on!\n",
|
||||
connector->name);
|
||||
connector->status = connector_status_disconnected;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ static u16 lerp_u16(u16 a, u16 b, s64 t)
|
|||
|
||||
s64 delta = drm_fixp_mul(b_fp - a_fp, t);
|
||||
|
||||
return drm_fixp2int(a_fp + delta);
|
||||
return drm_fixp2int_round(a_fp + delta);
|
||||
}
|
||||
|
||||
static s64 get_lut_index(const struct vkms_color_lut *lut, u16 channel_value)
|
||||
|
|
|
@ -53,7 +53,6 @@
|
|||
|
||||
#define RING_CTL(base) XE_REG((base) + 0x3c)
|
||||
#define RING_CTL_SIZE(size) ((size) - PAGE_SIZE) /* in bytes -> pages */
|
||||
#define RING_CTL_SIZE(size) ((size) - PAGE_SIZE) /* in bytes -> pages */
|
||||
|
||||
#define RING_START_UDW(base) XE_REG((base) + 0x48)
|
||||
|
||||
|
|
|
@ -1248,6 +1248,8 @@ static void __guc_exec_queue_fini_async(struct work_struct *w)
|
|||
|
||||
if (xe_exec_queue_is_lr(q))
|
||||
cancel_work_sync(&ge->lr_tdr);
|
||||
/* Confirm no work left behind accessing device structures */
|
||||
cancel_delayed_work_sync(&ge->sched.base.work_tdr);
|
||||
release_guc_id(guc, q);
|
||||
xe_sched_entity_fini(&ge->entity);
|
||||
xe_sched_fini(&ge->sched);
|
||||
|
|
|
@ -1689,7 +1689,7 @@ static int xe_oa_stream_init(struct xe_oa_stream *stream,
|
|||
stream->oa_buffer.format = &stream->oa->oa_formats[param->oa_format];
|
||||
|
||||
stream->sample = param->sample;
|
||||
stream->periodic = param->period_exponent > 0;
|
||||
stream->periodic = param->period_exponent >= 0;
|
||||
stream->period_exponent = param->period_exponent;
|
||||
stream->no_preempt = param->no_preempt;
|
||||
stream->wait_num_reports = param->wait_num_reports;
|
||||
|
@ -1970,6 +1970,7 @@ int xe_oa_stream_open_ioctl(struct drm_device *dev, u64 data, struct drm_file *f
|
|||
}
|
||||
|
||||
param.xef = xef;
|
||||
param.period_exponent = -1;
|
||||
ret = xe_oa_user_extensions(oa, XE_OA_USER_EXTN_FROM_OPEN, data, 0, ¶m);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -2024,7 +2025,7 @@ int xe_oa_stream_open_ioctl(struct drm_device *dev, u64 data, struct drm_file *f
|
|||
goto err_exec_q;
|
||||
}
|
||||
|
||||
if (param.period_exponent > 0) {
|
||||
if (param.period_exponent >= 0) {
|
||||
u64 oa_period, oa_freq_hz;
|
||||
|
||||
/* Requesting samples from OAG buffer is a privileged operation */
|
||||
|
|
|
@ -666,20 +666,33 @@ int xe_vm_userptr_pin(struct xe_vm *vm)
|
|||
|
||||
/* Collect invalidated userptrs */
|
||||
spin_lock(&vm->userptr.invalidated_lock);
|
||||
xe_assert(vm->xe, list_empty(&vm->userptr.repin_list));
|
||||
list_for_each_entry_safe(uvma, next, &vm->userptr.invalidated,
|
||||
userptr.invalidate_link) {
|
||||
list_del_init(&uvma->userptr.invalidate_link);
|
||||
list_move_tail(&uvma->userptr.repin_link,
|
||||
&vm->userptr.repin_list);
|
||||
list_add_tail(&uvma->userptr.repin_link,
|
||||
&vm->userptr.repin_list);
|
||||
}
|
||||
spin_unlock(&vm->userptr.invalidated_lock);
|
||||
|
||||
/* Pin and move to temporary list */
|
||||
/* Pin and move to bind list */
|
||||
list_for_each_entry_safe(uvma, next, &vm->userptr.repin_list,
|
||||
userptr.repin_link) {
|
||||
err = xe_vma_userptr_pin_pages(uvma);
|
||||
if (err == -EFAULT) {
|
||||
list_del_init(&uvma->userptr.repin_link);
|
||||
/*
|
||||
* We might have already done the pin once already, but
|
||||
* then had to retry before the re-bind happened, due
|
||||
* some other condition in the caller, but in the
|
||||
* meantime the userptr got dinged by the notifier such
|
||||
* that we need to revalidate here, but this time we hit
|
||||
* the EFAULT. In such a case make sure we remove
|
||||
* ourselves from the rebind list to avoid going down in
|
||||
* flames.
|
||||
*/
|
||||
if (!list_empty(&uvma->vma.combined_links.rebind))
|
||||
list_del_init(&uvma->vma.combined_links.rebind);
|
||||
|
||||
/* Wait for pending binds */
|
||||
xe_vm_lock(vm, false);
|
||||
|
@ -690,10 +703,10 @@ int xe_vm_userptr_pin(struct xe_vm *vm)
|
|||
err = xe_vm_invalidate_vma(&uvma->vma);
|
||||
xe_vm_unlock(vm);
|
||||
if (err)
|
||||
return err;
|
||||
break;
|
||||
} else {
|
||||
if (err < 0)
|
||||
return err;
|
||||
if (err)
|
||||
break;
|
||||
|
||||
list_del_init(&uvma->userptr.repin_link);
|
||||
list_move_tail(&uvma->vma.combined_links.rebind,
|
||||
|
@ -701,7 +714,19 @@ int xe_vm_userptr_pin(struct xe_vm *vm)
|
|||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
if (err) {
|
||||
down_write(&vm->userptr.notifier_lock);
|
||||
spin_lock(&vm->userptr.invalidated_lock);
|
||||
list_for_each_entry_safe(uvma, next, &vm->userptr.repin_list,
|
||||
userptr.repin_link) {
|
||||
list_del_init(&uvma->userptr.repin_link);
|
||||
list_move_tail(&uvma->userptr.invalidate_link,
|
||||
&vm->userptr.invalidated);
|
||||
}
|
||||
spin_unlock(&vm->userptr.invalidated_lock);
|
||||
up_write(&vm->userptr.notifier_lock);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1066,6 +1091,7 @@ static void xe_vma_destroy(struct xe_vma *vma, struct dma_fence *fence)
|
|||
xe_assert(vm->xe, vma->gpuva.flags & XE_VMA_DESTROYED);
|
||||
|
||||
spin_lock(&vm->userptr.invalidated_lock);
|
||||
xe_assert(vm->xe, list_empty(&to_userptr_vma(vma)->userptr.repin_link));
|
||||
list_del(&to_userptr_vma(vma)->userptr.invalidate_link);
|
||||
spin_unlock(&vm->userptr.invalidated_lock);
|
||||
} else if (!xe_vma_is_null(vma)) {
|
||||
|
|
Loading…
Reference in New Issue