mirror of
https://github.com/torvalds/linux.git
synced 2026-05-31 02:24:24 +02:00
drm fixes for 6.16-rc3
msm: - Display: - Fixed DP output on SDM845 - Fixed 10nm DSI PLL init - GPU: - SUBMIT ioctl error path leak fixes - drm half of stall-on-fault fixes. - a7xx: Missing CP_RESET_CONTEXT_STATE - Skip GPU component bind if GPU is not in the device table. i915: - Fix MIPI vtotal programming off by one on Broxton - Fix PMU code for GCOV and AutoFDO enabled build xe: - A workaround update - Fix memset on iomem - Fix early wedge on GuC Load failure amdgpu: - DP tunneling fix - LTTPR fix - DSC fix - DML2.x ABGR16161616 fix - RMCM fix - Backlight fixes - GFX11 kicker support - SDMA reset fixes - VCN 5.0.1 fix - Reset fix - Misc small fixes amdkfd: - SDMA reset fix - Fix race in GWS scheduling nouveau: - update docs reference - fix backlight name buffer size - fix UAF in r535 gsp rpc msg - fix undefined shift mgag200: - drop export header ast: - drop export header malidp: - drop informational error ssd130x: - fix clear columns etnaviv: - scheduler locking fix v3d: - null pointer crash fix -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEEKbZHaGwW9KfbeusDHTzWXnEhr4FAmhU0/8ACgkQDHTzWXnE hr780g//dzOqGoNqwd4nh7zHLYuxSmVvJXcaFwOoYbnhrB54rW3i06ROu28U8UPL xclwyYFjALd+ZwDw0QjN2hOfR8xnUcxbT+EpoQ/Eu2RoJiithpXkZzlkeZal0QPt icoy0GzZEymh3HnvkX+lRqnoX64if7K0UYXtVrJ+2ewiosA885uBqvA0AXsi24GU ExM3cRC+FOkKOSN5ZJlgtFHdSUk8bDMaovxhRCB8SZTbobG0eXWyn68urW+M/nGm vDhvJ9oxfIoZJ586Kvb7B1AEeIr3juOs6k3CnPvBG3g9ZUuxJi4OUUrY6n7XIWvx K/5noPH23kVrz7kvdAaPmX9uzsQPqF2g2cL+KpzE2AaQR4IZwsjt5cvYDaWLhBdX sPdynJOXoU2AbAal+k5y6sTb3vDTKbTo1RN8NW9N9N449Nnd0qfRsq6gVqsD15ok Ro8b2QGAQ6oBuvStGjC37AfleBal91+0U8LEgJO60tRrv1cNQhT1ic/bbaNjBNlZ kzVSiLRIpsmx2NBgpYKrq/ESjAmfr3ZVLwf8XW784HM6WJEcp0D4JJkIbtXLwauN qY3YTBP/pLC3+1LSnvtk2CbQiuAb8W8qhzfpl3UMO6PGDzt0xOnadTmmLMr6k+Gg SqD7bRFNjJ5jLwsD0zGtxoq/8jms/wxuQdwoMZxC0767CRD7NEg= =8R74 -----END PGP SIGNATURE----- Merge tag 'drm-fixes-2025-06-20' of https://gitlab.freedesktop.org/drm/kernel Pull drm fixes from Dave Airlie: "Bit of an uptick in fixes for rc3, msm and amdgpu leading the way, with i915/xe/nouveau with a few each and then some scattered misc bits, nothing looks too crazy: msm: - Display: - Fixed DP output on SDM845 - Fixed 10nm DSI PLL init - GPU: - SUBMIT ioctl error path leak fixes - drm half of stall-on-fault fixes - a7xx: Missing CP_RESET_CONTEXT_STATE - Skip GPU component bind if GPU is not in the device table i915: - Fix MIPI vtotal programming off by one on Broxton - Fix PMU code for GCOV and AutoFDO enabled build xe: - A workaround update - Fix memset on iomem - Fix early wedge on GuC Load failure amdgpu: - DP tunneling fix - LTTPR fix - DSC fix - DML2.x ABGR16161616 fix - RMCM fix - Backlight fixes - GFX11 kicker support - SDMA reset fixes - VCN 5.0.1 fix - Reset fix - Misc small fixes amdkfd: - SDMA reset fix - Fix race in GWS scheduling nouveau: - update docs reference - fix backlight name buffer size - fix UAF in r535 gsp rpc msg - fix undefined shift mgag200: - drop export header ast: - drop export header malidp: - drop informational error ssd130x: - fix clear columns etnaviv: - scheduler locking fix v3d: - null pointer crash fix" * tag 'drm-fixes-2025-06-20' of https://gitlab.freedesktop.org/drm/kernel: (50 commits) drm/xe: Fix early wedge on GuC load failure drm/xe: Fix memset on iomem drm/xe/bmg: Update Wa_16023588340 drm/amdgpu/sdma5.2: init engine reset mutex drm/amdkfd: Fix race in GWS queue scheduling drm/amdgpu/sdma5: init engine reset mutex drm/amdgpu: switch job hw_fence to amdgpu_fence drm/amdgpu: Fix SDMA UTC_L1 handling during start/stop sequences drm/amdgpu: Release reset locks during failures drm/amd/display: Check dce_hwseq before dereferencing it drm/amdgpu: VCN v5_0_1 to prevent FW checking RB during DPG pause drm/amdgpu: Use logical instance ID for SDMA v4_4_2 queue operations drm/amdgpu: Fix SDMA engine reset with logical instance ID drm/amdgpu: add kicker fws loading for gfx11/smu13/psp13 drm/amdgpu: Add kicker device detection drm/amd/display: Export full brightness range to userspace drm/amd/display: Only read ACPI backlight caps once drm/amd/display: Fix RMCM programming seq errors drm/amd/display: Fix mpv playback corruption on weston drm/amd/display: Add more checks for DSC / HUBP ONO guarantees ...
This commit is contained in:
commit
5f2b6c5f6b
|
|
@ -25,7 +25,7 @@ providing a consistent API to upper layers of the driver stack.
|
|||
GSP Support
|
||||
------------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c
|
||||
.. kernel-doc:: drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/rpc.c
|
||||
:doc: GSP message queue element
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h
|
||||
|
|
|
|||
|
|
@ -1902,7 +1902,7 @@ static void amdgpu_ib_preempt_mark_partial_job(struct amdgpu_ring *ring)
|
|||
continue;
|
||||
}
|
||||
job = to_amdgpu_job(s_job);
|
||||
if (preempted && (&job->hw_fence) == fence)
|
||||
if (preempted && (&job->hw_fence.base) == fence)
|
||||
/* mark the job as preempted */
|
||||
job->preemption_status |= AMDGPU_IB_PREEMPTED;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6019,16 +6019,12 @@ static int amdgpu_device_health_check(struct list_head *device_list_handle)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int amdgpu_device_halt_activities(struct amdgpu_device *adev,
|
||||
struct amdgpu_job *job,
|
||||
struct amdgpu_reset_context *reset_context,
|
||||
struct list_head *device_list,
|
||||
struct amdgpu_hive_info *hive,
|
||||
bool need_emergency_restart)
|
||||
static int amdgpu_device_recovery_prepare(struct amdgpu_device *adev,
|
||||
struct list_head *device_list,
|
||||
struct amdgpu_hive_info *hive)
|
||||
{
|
||||
struct list_head *device_list_handle = NULL;
|
||||
struct amdgpu_device *tmp_adev = NULL;
|
||||
int i, r = 0;
|
||||
int r;
|
||||
|
||||
/*
|
||||
* Build list of devices to reset.
|
||||
|
|
@ -6045,26 +6041,54 @@ static int amdgpu_device_halt_activities(struct amdgpu_device *adev,
|
|||
}
|
||||
if (!list_is_first(&adev->reset_list, device_list))
|
||||
list_rotate_to_front(&adev->reset_list, device_list);
|
||||
device_list_handle = device_list;
|
||||
} else {
|
||||
list_add_tail(&adev->reset_list, device_list);
|
||||
device_list_handle = device_list;
|
||||
}
|
||||
|
||||
if (!amdgpu_sriov_vf(adev) && (!adev->pcie_reset_ctx.occurs_dpc)) {
|
||||
r = amdgpu_device_health_check(device_list_handle);
|
||||
r = amdgpu_device_health_check(device_list);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* We need to lock reset domain only once both for XGMI and single device */
|
||||
tmp_adev = list_first_entry(device_list_handle, struct amdgpu_device,
|
||||
reset_list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void amdgpu_device_recovery_get_reset_lock(struct amdgpu_device *adev,
|
||||
struct list_head *device_list)
|
||||
{
|
||||
struct amdgpu_device *tmp_adev = NULL;
|
||||
|
||||
if (list_empty(device_list))
|
||||
return;
|
||||
tmp_adev =
|
||||
list_first_entry(device_list, struct amdgpu_device, reset_list);
|
||||
amdgpu_device_lock_reset_domain(tmp_adev->reset_domain);
|
||||
}
|
||||
|
||||
static void amdgpu_device_recovery_put_reset_lock(struct amdgpu_device *adev,
|
||||
struct list_head *device_list)
|
||||
{
|
||||
struct amdgpu_device *tmp_adev = NULL;
|
||||
|
||||
if (list_empty(device_list))
|
||||
return;
|
||||
tmp_adev =
|
||||
list_first_entry(device_list, struct amdgpu_device, reset_list);
|
||||
amdgpu_device_unlock_reset_domain(tmp_adev->reset_domain);
|
||||
}
|
||||
|
||||
static int amdgpu_device_halt_activities(
|
||||
struct amdgpu_device *adev, struct amdgpu_job *job,
|
||||
struct amdgpu_reset_context *reset_context,
|
||||
struct list_head *device_list, struct amdgpu_hive_info *hive,
|
||||
bool need_emergency_restart)
|
||||
{
|
||||
struct amdgpu_device *tmp_adev = NULL;
|
||||
int i, r = 0;
|
||||
|
||||
/* block all schedulers and reset given job's ring */
|
||||
list_for_each_entry(tmp_adev, device_list_handle, reset_list) {
|
||||
|
||||
list_for_each_entry(tmp_adev, device_list, reset_list) {
|
||||
amdgpu_device_set_mp1_state(tmp_adev);
|
||||
|
||||
/*
|
||||
|
|
@ -6252,11 +6276,6 @@ static void amdgpu_device_gpu_resume(struct amdgpu_device *adev,
|
|||
amdgpu_ras_set_error_query_ready(tmp_adev, true);
|
||||
|
||||
}
|
||||
|
||||
tmp_adev = list_first_entry(device_list, struct amdgpu_device,
|
||||
reset_list);
|
||||
amdgpu_device_unlock_reset_domain(tmp_adev->reset_domain);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -6324,10 +6343,16 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
|
|||
reset_context->hive = hive;
|
||||
INIT_LIST_HEAD(&device_list);
|
||||
|
||||
if (amdgpu_device_recovery_prepare(adev, &device_list, hive))
|
||||
goto end_reset;
|
||||
|
||||
/* We need to lock reset domain only once both for XGMI and single device */
|
||||
amdgpu_device_recovery_get_reset_lock(adev, &device_list);
|
||||
|
||||
r = amdgpu_device_halt_activities(adev, job, reset_context, &device_list,
|
||||
hive, need_emergency_restart);
|
||||
if (r)
|
||||
goto end_reset;
|
||||
goto reset_unlock;
|
||||
|
||||
if (need_emergency_restart)
|
||||
goto skip_sched_resume;
|
||||
|
|
@ -6337,7 +6362,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
|
|||
*
|
||||
* job->base holds a reference to parent fence
|
||||
*/
|
||||
if (job && dma_fence_is_signaled(&job->hw_fence)) {
|
||||
if (job && dma_fence_is_signaled(&job->hw_fence.base)) {
|
||||
job_signaled = true;
|
||||
dev_info(adev->dev, "Guilty job already signaled, skipping HW reset");
|
||||
goto skip_hw_reset;
|
||||
|
|
@ -6345,13 +6370,15 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
|
|||
|
||||
r = amdgpu_device_asic_reset(adev, &device_list, reset_context);
|
||||
if (r)
|
||||
goto end_reset;
|
||||
goto reset_unlock;
|
||||
skip_hw_reset:
|
||||
r = amdgpu_device_sched_resume(&device_list, reset_context, job_signaled);
|
||||
if (r)
|
||||
goto end_reset;
|
||||
goto reset_unlock;
|
||||
skip_sched_resume:
|
||||
amdgpu_device_gpu_resume(adev, &device_list, need_emergency_restart);
|
||||
reset_unlock:
|
||||
amdgpu_device_recovery_put_reset_lock(adev, &device_list);
|
||||
end_reset:
|
||||
if (hive) {
|
||||
mutex_unlock(&hive->hive_lock);
|
||||
|
|
@ -6763,6 +6790,8 @@ pci_ers_result_t amdgpu_pci_error_detected(struct pci_dev *pdev, pci_channel_sta
|
|||
memset(&reset_context, 0, sizeof(reset_context));
|
||||
INIT_LIST_HEAD(&device_list);
|
||||
|
||||
amdgpu_device_recovery_prepare(adev, &device_list, hive);
|
||||
amdgpu_device_recovery_get_reset_lock(adev, &device_list);
|
||||
r = amdgpu_device_halt_activities(adev, NULL, &reset_context, &device_list,
|
||||
hive, false);
|
||||
if (hive) {
|
||||
|
|
@ -6880,8 +6909,8 @@ pci_ers_result_t amdgpu_pci_slot_reset(struct pci_dev *pdev)
|
|||
if (hive) {
|
||||
list_for_each_entry(tmp_adev, &device_list, reset_list)
|
||||
amdgpu_device_unset_mp1_state(tmp_adev);
|
||||
amdgpu_device_unlock_reset_domain(adev->reset_domain);
|
||||
}
|
||||
amdgpu_device_recovery_put_reset_lock(adev, &device_list);
|
||||
}
|
||||
|
||||
if (hive) {
|
||||
|
|
@ -6927,6 +6956,7 @@ void amdgpu_pci_resume(struct pci_dev *pdev)
|
|||
|
||||
amdgpu_device_sched_resume(&device_list, NULL, NULL);
|
||||
amdgpu_device_gpu_resume(adev, &device_list, false);
|
||||
amdgpu_device_recovery_put_reset_lock(adev, &device_list);
|
||||
adev->pcie_reset_ctx.occurs_dpc = false;
|
||||
|
||||
if (hive) {
|
||||
|
|
|
|||
|
|
@ -41,22 +41,6 @@
|
|||
#include "amdgpu_trace.h"
|
||||
#include "amdgpu_reset.h"
|
||||
|
||||
/*
|
||||
* Fences mark an event in the GPUs pipeline and are used
|
||||
* for GPU/CPU synchronization. When the fence is written,
|
||||
* it is expected that all buffers associated with that fence
|
||||
* are no longer in use by the associated ring on the GPU and
|
||||
* that the relevant GPU caches have been flushed.
|
||||
*/
|
||||
|
||||
struct amdgpu_fence {
|
||||
struct dma_fence base;
|
||||
|
||||
/* RB, DMA, etc. */
|
||||
struct amdgpu_ring *ring;
|
||||
ktime_t start_timestamp;
|
||||
};
|
||||
|
||||
static struct kmem_cache *amdgpu_fence_slab;
|
||||
|
||||
int amdgpu_fence_slab_init(void)
|
||||
|
|
@ -151,12 +135,12 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **f, struct amd
|
|||
am_fence = kmem_cache_alloc(amdgpu_fence_slab, GFP_ATOMIC);
|
||||
if (am_fence == NULL)
|
||||
return -ENOMEM;
|
||||
fence = &am_fence->base;
|
||||
am_fence->ring = ring;
|
||||
} else {
|
||||
/* take use of job-embedded fence */
|
||||
fence = &job->hw_fence;
|
||||
am_fence = &job->hw_fence;
|
||||
}
|
||||
fence = &am_fence->base;
|
||||
am_fence->ring = ring;
|
||||
|
||||
seq = ++ring->fence_drv.sync_seq;
|
||||
if (job && job->job_run_counter) {
|
||||
|
|
@ -718,7 +702,7 @@ void amdgpu_fence_driver_clear_job_fences(struct amdgpu_ring *ring)
|
|||
* it right here or we won't be able to track them in fence_drv
|
||||
* and they will remain unsignaled during sa_bo free.
|
||||
*/
|
||||
job = container_of(old, struct amdgpu_job, hw_fence);
|
||||
job = container_of(old, struct amdgpu_job, hw_fence.base);
|
||||
if (!job->base.s_fence && !dma_fence_is_signaled(old))
|
||||
dma_fence_signal(old);
|
||||
RCU_INIT_POINTER(*ptr, NULL);
|
||||
|
|
@ -780,7 +764,7 @@ static const char *amdgpu_fence_get_timeline_name(struct dma_fence *f)
|
|||
|
||||
static const char *amdgpu_job_fence_get_timeline_name(struct dma_fence *f)
|
||||
{
|
||||
struct amdgpu_job *job = container_of(f, struct amdgpu_job, hw_fence);
|
||||
struct amdgpu_job *job = container_of(f, struct amdgpu_job, hw_fence.base);
|
||||
|
||||
return (const char *)to_amdgpu_ring(job->base.sched)->name;
|
||||
}
|
||||
|
|
@ -810,7 +794,7 @@ static bool amdgpu_fence_enable_signaling(struct dma_fence *f)
|
|||
*/
|
||||
static bool amdgpu_job_fence_enable_signaling(struct dma_fence *f)
|
||||
{
|
||||
struct amdgpu_job *job = container_of(f, struct amdgpu_job, hw_fence);
|
||||
struct amdgpu_job *job = container_of(f, struct amdgpu_job, hw_fence.base);
|
||||
|
||||
if (!timer_pending(&to_amdgpu_ring(job->base.sched)->fence_drv.fallback_timer))
|
||||
amdgpu_fence_schedule_fallback(to_amdgpu_ring(job->base.sched));
|
||||
|
|
@ -845,7 +829,7 @@ static void amdgpu_job_fence_free(struct rcu_head *rcu)
|
|||
struct dma_fence *f = container_of(rcu, struct dma_fence, rcu);
|
||||
|
||||
/* free job if fence has a parent job */
|
||||
kfree(container_of(f, struct amdgpu_job, hw_fence));
|
||||
kfree(container_of(f, struct amdgpu_job, hw_fence.base));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -272,8 +272,8 @@ void amdgpu_job_free_resources(struct amdgpu_job *job)
|
|||
/* Check if any fences where initialized */
|
||||
if (job->base.s_fence && job->base.s_fence->finished.ops)
|
||||
f = &job->base.s_fence->finished;
|
||||
else if (job->hw_fence.ops)
|
||||
f = &job->hw_fence;
|
||||
else if (job->hw_fence.base.ops)
|
||||
f = &job->hw_fence.base;
|
||||
else
|
||||
f = NULL;
|
||||
|
||||
|
|
@ -290,10 +290,10 @@ static void amdgpu_job_free_cb(struct drm_sched_job *s_job)
|
|||
amdgpu_sync_free(&job->explicit_sync);
|
||||
|
||||
/* only put the hw fence if has embedded fence */
|
||||
if (!job->hw_fence.ops)
|
||||
if (!job->hw_fence.base.ops)
|
||||
kfree(job);
|
||||
else
|
||||
dma_fence_put(&job->hw_fence);
|
||||
dma_fence_put(&job->hw_fence.base);
|
||||
}
|
||||
|
||||
void amdgpu_job_set_gang_leader(struct amdgpu_job *job,
|
||||
|
|
@ -322,10 +322,10 @@ void amdgpu_job_free(struct amdgpu_job *job)
|
|||
if (job->gang_submit != &job->base.s_fence->scheduled)
|
||||
dma_fence_put(job->gang_submit);
|
||||
|
||||
if (!job->hw_fence.ops)
|
||||
if (!job->hw_fence.base.ops)
|
||||
kfree(job);
|
||||
else
|
||||
dma_fence_put(&job->hw_fence);
|
||||
dma_fence_put(&job->hw_fence.base);
|
||||
}
|
||||
|
||||
struct dma_fence *amdgpu_job_submit(struct amdgpu_job *job)
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ struct amdgpu_job {
|
|||
struct drm_sched_job base;
|
||||
struct amdgpu_vm *vm;
|
||||
struct amdgpu_sync explicit_sync;
|
||||
struct dma_fence hw_fence;
|
||||
struct amdgpu_fence hw_fence;
|
||||
struct dma_fence *gang_submit;
|
||||
uint32_t preamble_status;
|
||||
uint32_t preemption_status;
|
||||
|
|
|
|||
|
|
@ -3522,8 +3522,12 @@ int psp_init_sos_microcode(struct psp_context *psp, const char *chip_name)
|
|||
uint8_t *ucode_array_start_addr;
|
||||
int err = 0;
|
||||
|
||||
err = amdgpu_ucode_request(adev, &adev->psp.sos_fw, AMDGPU_UCODE_REQUIRED,
|
||||
"amdgpu/%s_sos.bin", chip_name);
|
||||
if (amdgpu_is_kicker_fw(adev))
|
||||
err = amdgpu_ucode_request(adev, &adev->psp.sos_fw, AMDGPU_UCODE_REQUIRED,
|
||||
"amdgpu/%s_sos_kicker.bin", chip_name);
|
||||
else
|
||||
err = amdgpu_ucode_request(adev, &adev->psp.sos_fw, AMDGPU_UCODE_REQUIRED,
|
||||
"amdgpu/%s_sos.bin", chip_name);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
|
|
@ -3799,8 +3803,12 @@ int psp_init_ta_microcode(struct psp_context *psp, const char *chip_name)
|
|||
struct amdgpu_device *adev = psp->adev;
|
||||
int err;
|
||||
|
||||
err = amdgpu_ucode_request(adev, &adev->psp.ta_fw, AMDGPU_UCODE_REQUIRED,
|
||||
"amdgpu/%s_ta.bin", chip_name);
|
||||
if (amdgpu_is_kicker_fw(adev))
|
||||
err = amdgpu_ucode_request(adev, &adev->psp.ta_fw, AMDGPU_UCODE_REQUIRED,
|
||||
"amdgpu/%s_ta_kicker.bin", chip_name);
|
||||
else
|
||||
err = amdgpu_ucode_request(adev, &adev->psp.ta_fw, AMDGPU_UCODE_REQUIRED,
|
||||
"amdgpu/%s_ta.bin", chip_name);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
|
|
|||
|
|
@ -127,6 +127,22 @@ struct amdgpu_fence_driver {
|
|||
struct dma_fence **fences;
|
||||
};
|
||||
|
||||
/*
|
||||
* Fences mark an event in the GPUs pipeline and are used
|
||||
* for GPU/CPU synchronization. When the fence is written,
|
||||
* it is expected that all buffers associated with that fence
|
||||
* are no longer in use by the associated ring on the GPU and
|
||||
* that the relevant GPU caches have been flushed.
|
||||
*/
|
||||
|
||||
struct amdgpu_fence {
|
||||
struct dma_fence base;
|
||||
|
||||
/* RB, DMA, etc. */
|
||||
struct amdgpu_ring *ring;
|
||||
ktime_t start_timestamp;
|
||||
};
|
||||
|
||||
extern const struct drm_sched_backend_ops amdgpu_sched_ops;
|
||||
|
||||
void amdgpu_fence_driver_clear_job_fences(struct amdgpu_ring *ring);
|
||||
|
|
|
|||
|
|
@ -540,8 +540,10 @@ static int amdgpu_sdma_soft_reset(struct amdgpu_device *adev, u32 instance_id)
|
|||
case IP_VERSION(4, 4, 2):
|
||||
case IP_VERSION(4, 4, 4):
|
||||
case IP_VERSION(4, 4, 5):
|
||||
/* For SDMA 4.x, use the existing DPM interface for backward compatibility */
|
||||
r = amdgpu_dpm_reset_sdma(adev, 1 << instance_id);
|
||||
/* For SDMA 4.x, use the existing DPM interface for backward compatibility,
|
||||
* we need to convert the logical instance ID to physical instance ID before reset.
|
||||
*/
|
||||
r = amdgpu_dpm_reset_sdma(adev, 1 << GET_INST(SDMA0, instance_id));
|
||||
break;
|
||||
case IP_VERSION(5, 0, 0):
|
||||
case IP_VERSION(5, 0, 1):
|
||||
|
|
@ -568,7 +570,7 @@ static int amdgpu_sdma_soft_reset(struct amdgpu_device *adev, u32 instance_id)
|
|||
/**
|
||||
* amdgpu_sdma_reset_engine - Reset a specific SDMA engine
|
||||
* @adev: Pointer to the AMDGPU device
|
||||
* @instance_id: ID of the SDMA engine instance to reset
|
||||
* @instance_id: Logical ID of the SDMA engine instance to reset
|
||||
*
|
||||
* Returns: 0 on success, or a negative error code on failure.
|
||||
*/
|
||||
|
|
@ -601,7 +603,7 @@ int amdgpu_sdma_reset_engine(struct amdgpu_device *adev, uint32_t instance_id)
|
|||
/* Perform the SDMA reset for the specified instance */
|
||||
ret = amdgpu_sdma_soft_reset(adev, instance_id);
|
||||
if (ret) {
|
||||
dev_err(adev->dev, "Failed to reset SDMA instance %u\n", instance_id);
|
||||
dev_err(adev->dev, "Failed to reset SDMA logical instance %u\n", instance_id);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,10 @@
|
|||
|
||||
#define AMDGPU_UCODE_NAME_MAX (128)
|
||||
|
||||
static const struct kicker_device kicker_device_list[] = {
|
||||
{0x744B, 0x00},
|
||||
};
|
||||
|
||||
static void amdgpu_ucode_print_common_hdr(const struct common_firmware_header *hdr)
|
||||
{
|
||||
DRM_DEBUG("size_bytes: %u\n", le32_to_cpu(hdr->size_bytes));
|
||||
|
|
@ -1387,6 +1391,19 @@ static const char *amdgpu_ucode_legacy_naming(struct amdgpu_device *adev, int bl
|
|||
return NULL;
|
||||
}
|
||||
|
||||
bool amdgpu_is_kicker_fw(struct amdgpu_device *adev)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(kicker_device_list); i++) {
|
||||
if (adev->pdev->device == kicker_device_list[i].device &&
|
||||
adev->pdev->revision == kicker_device_list[i].revision)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void amdgpu_ucode_ip_version_decode(struct amdgpu_device *adev, int block_type, char *ucode_prefix, int len)
|
||||
{
|
||||
int maj, min, rev;
|
||||
|
|
|
|||
|
|
@ -605,6 +605,11 @@ struct amdgpu_firmware {
|
|||
uint32_t pldm_version;
|
||||
};
|
||||
|
||||
struct kicker_device{
|
||||
unsigned short device;
|
||||
u8 revision;
|
||||
};
|
||||
|
||||
void amdgpu_ucode_print_mc_hdr(const struct common_firmware_header *hdr);
|
||||
void amdgpu_ucode_print_smc_hdr(const struct common_firmware_header *hdr);
|
||||
void amdgpu_ucode_print_imu_hdr(const struct common_firmware_header *hdr);
|
||||
|
|
@ -632,5 +637,6 @@ amdgpu_ucode_get_load_type(struct amdgpu_device *adev, int load_type);
|
|||
const char *amdgpu_ucode_name(enum AMDGPU_UCODE_ID ucode_id);
|
||||
|
||||
void amdgpu_ucode_ip_version_decode(struct amdgpu_device *adev, int block_type, char *ucode_prefix, int len);
|
||||
bool amdgpu_is_kicker_fw(struct amdgpu_device *adev);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ MODULE_FIRMWARE("amdgpu/gc_11_0_0_pfp.bin");
|
|||
MODULE_FIRMWARE("amdgpu/gc_11_0_0_me.bin");
|
||||
MODULE_FIRMWARE("amdgpu/gc_11_0_0_mec.bin");
|
||||
MODULE_FIRMWARE("amdgpu/gc_11_0_0_rlc.bin");
|
||||
MODULE_FIRMWARE("amdgpu/gc_11_0_0_rlc_kicker.bin");
|
||||
MODULE_FIRMWARE("amdgpu/gc_11_0_0_rlc_1.bin");
|
||||
MODULE_FIRMWARE("amdgpu/gc_11_0_0_toc.bin");
|
||||
MODULE_FIRMWARE("amdgpu/gc_11_0_1_pfp.bin");
|
||||
|
|
@ -759,6 +760,10 @@ static int gfx_v11_0_init_microcode(struct amdgpu_device *adev)
|
|||
err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw,
|
||||
AMDGPU_UCODE_REQUIRED,
|
||||
"amdgpu/gc_11_0_0_rlc_1.bin");
|
||||
else if (amdgpu_is_kicker_fw(adev))
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw,
|
||||
AMDGPU_UCODE_REQUIRED,
|
||||
"amdgpu/%s_rlc_kicker.bin", ucode_prefix);
|
||||
else
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw,
|
||||
AMDGPU_UCODE_REQUIRED,
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include "gc/gc_11_0_0_sh_mask.h"
|
||||
|
||||
MODULE_FIRMWARE("amdgpu/gc_11_0_0_imu.bin");
|
||||
MODULE_FIRMWARE("amdgpu/gc_11_0_0_imu_kicker.bin");
|
||||
MODULE_FIRMWARE("amdgpu/gc_11_0_1_imu.bin");
|
||||
MODULE_FIRMWARE("amdgpu/gc_11_0_2_imu.bin");
|
||||
MODULE_FIRMWARE("amdgpu/gc_11_0_3_imu.bin");
|
||||
|
|
@ -51,8 +52,12 @@ static int imu_v11_0_init_microcode(struct amdgpu_device *adev)
|
|||
DRM_DEBUG("\n");
|
||||
|
||||
amdgpu_ucode_ip_version_decode(adev, GC_HWIP, ucode_prefix, sizeof(ucode_prefix));
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.imu_fw, AMDGPU_UCODE_REQUIRED,
|
||||
"amdgpu/%s_imu.bin", ucode_prefix);
|
||||
if (amdgpu_is_kicker_fw(adev))
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.imu_fw, AMDGPU_UCODE_REQUIRED,
|
||||
"amdgpu/%s_imu_kicker.bin", ucode_prefix);
|
||||
else
|
||||
err = amdgpu_ucode_request(adev, &adev->gfx.imu_fw, AMDGPU_UCODE_REQUIRED,
|
||||
"amdgpu/%s_imu.bin", ucode_prefix);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,9 @@ MODULE_FIRMWARE("amdgpu/psp_13_0_5_ta.bin");
|
|||
MODULE_FIRMWARE("amdgpu/psp_13_0_8_toc.bin");
|
||||
MODULE_FIRMWARE("amdgpu/psp_13_0_8_ta.bin");
|
||||
MODULE_FIRMWARE("amdgpu/psp_13_0_0_sos.bin");
|
||||
MODULE_FIRMWARE("amdgpu/psp_13_0_0_sos_kicker.bin");
|
||||
MODULE_FIRMWARE("amdgpu/psp_13_0_0_ta.bin");
|
||||
MODULE_FIRMWARE("amdgpu/psp_13_0_0_ta_kicker.bin");
|
||||
MODULE_FIRMWARE("amdgpu/psp_13_0_7_sos.bin");
|
||||
MODULE_FIRMWARE("amdgpu/psp_13_0_7_ta.bin");
|
||||
MODULE_FIRMWARE("amdgpu/psp_13_0_10_sos.bin");
|
||||
|
|
|
|||
|
|
@ -490,7 +490,7 @@ static void sdma_v4_4_2_inst_gfx_stop(struct amdgpu_device *adev,
|
|||
{
|
||||
struct amdgpu_ring *sdma[AMDGPU_MAX_SDMA_INSTANCES];
|
||||
u32 doorbell_offset, doorbell;
|
||||
u32 rb_cntl, ib_cntl;
|
||||
u32 rb_cntl, ib_cntl, sdma_cntl;
|
||||
int i;
|
||||
|
||||
for_each_inst(i, inst_mask) {
|
||||
|
|
@ -502,6 +502,9 @@ static void sdma_v4_4_2_inst_gfx_stop(struct amdgpu_device *adev,
|
|||
ib_cntl = RREG32_SDMA(i, regSDMA_GFX_IB_CNTL);
|
||||
ib_cntl = REG_SET_FIELD(ib_cntl, SDMA_GFX_IB_CNTL, IB_ENABLE, 0);
|
||||
WREG32_SDMA(i, regSDMA_GFX_IB_CNTL, ib_cntl);
|
||||
sdma_cntl = RREG32_SDMA(i, regSDMA_CNTL);
|
||||
sdma_cntl = REG_SET_FIELD(sdma_cntl, SDMA_CNTL, UTC_L1_ENABLE, 0);
|
||||
WREG32_SDMA(i, regSDMA_CNTL, sdma_cntl);
|
||||
|
||||
if (sdma[i]->use_doorbell) {
|
||||
doorbell = RREG32_SDMA(i, regSDMA_GFX_DOORBELL);
|
||||
|
|
@ -995,6 +998,7 @@ static int sdma_v4_4_2_inst_start(struct amdgpu_device *adev,
|
|||
/* set utc l1 enable flag always to 1 */
|
||||
temp = RREG32_SDMA(i, regSDMA_CNTL);
|
||||
temp = REG_SET_FIELD(temp, SDMA_CNTL, UTC_L1_ENABLE, 1);
|
||||
WREG32_SDMA(i, regSDMA_CNTL, temp);
|
||||
|
||||
if (amdgpu_ip_version(adev, SDMA0_HWIP, 0) < IP_VERSION(4, 4, 5)) {
|
||||
/* enable context empty interrupt during initialization */
|
||||
|
|
@ -1670,7 +1674,7 @@ static bool sdma_v4_4_2_page_ring_is_guilty(struct amdgpu_ring *ring)
|
|||
static int sdma_v4_4_2_reset_queue(struct amdgpu_ring *ring, unsigned int vmid)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
u32 id = GET_INST(SDMA0, ring->me);
|
||||
u32 id = ring->me;
|
||||
int r;
|
||||
|
||||
if (!(adev->sdma.supported_reset & AMDGPU_RESET_TYPE_PER_QUEUE))
|
||||
|
|
@ -1686,7 +1690,7 @@ static int sdma_v4_4_2_reset_queue(struct amdgpu_ring *ring, unsigned int vmid)
|
|||
static int sdma_v4_4_2_stop_queue(struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
u32 instance_id = GET_INST(SDMA0, ring->me);
|
||||
u32 instance_id = ring->me;
|
||||
u32 inst_mask;
|
||||
uint64_t rptr;
|
||||
|
||||
|
|
|
|||
|
|
@ -1399,6 +1399,7 @@ static int sdma_v5_0_sw_init(struct amdgpu_ip_block *ip_block)
|
|||
return r;
|
||||
|
||||
for (i = 0; i < adev->sdma.num_instances; i++) {
|
||||
mutex_init(&adev->sdma.instance[i].engine_reset_mutex);
|
||||
adev->sdma.instance[i].funcs = &sdma_v5_0_sdma_funcs;
|
||||
ring = &adev->sdma.instance[i].ring;
|
||||
ring->ring_obj = NULL;
|
||||
|
|
|
|||
|
|
@ -1318,6 +1318,7 @@ static int sdma_v5_2_sw_init(struct amdgpu_ip_block *ip_block)
|
|||
}
|
||||
|
||||
for (i = 0; i < adev->sdma.num_instances; i++) {
|
||||
mutex_init(&adev->sdma.instance[i].engine_reset_mutex);
|
||||
adev->sdma.instance[i].funcs = &sdma_v5_2_sdma_funcs;
|
||||
ring = &adev->sdma.instance[i].ring;
|
||||
ring->ring_obj = NULL;
|
||||
|
|
|
|||
|
|
@ -669,6 +669,9 @@ static int vcn_v5_0_1_start_dpg_mode(struct amdgpu_vcn_inst *vinst,
|
|||
if (indirect)
|
||||
amdgpu_vcn_psp_update_sram(adev, inst_idx, AMDGPU_UCODE_ID_VCN0_RAM);
|
||||
|
||||
/* resetting ring, fw should not check RB ring */
|
||||
fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET;
|
||||
|
||||
/* Pause dpg */
|
||||
vcn_v5_0_1_pause_dpg_mode(vinst, &state);
|
||||
|
||||
|
|
@ -681,7 +684,7 @@ static int vcn_v5_0_1_start_dpg_mode(struct amdgpu_vcn_inst *vinst,
|
|||
tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE);
|
||||
tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK);
|
||||
WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp);
|
||||
fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET;
|
||||
|
||||
WREG32_SOC15(VCN, vcn_inst, regUVD_RB_RPTR, 0);
|
||||
WREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR, 0);
|
||||
|
||||
|
|
@ -692,6 +695,7 @@ static int vcn_v5_0_1_start_dpg_mode(struct amdgpu_vcn_inst *vinst,
|
|||
tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE);
|
||||
tmp |= VCN_RB_ENABLE__RB1_EN_MASK;
|
||||
WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp);
|
||||
/* resetting done, fw can check RB ring */
|
||||
fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF);
|
||||
|
||||
WREG32_SOC15(VCN, vcn_inst, regVCN_RB1_DB_CTRL,
|
||||
|
|
|
|||
|
|
@ -240,7 +240,7 @@ static int pm_map_queues_v9(struct packet_manager *pm, uint32_t *buffer,
|
|||
|
||||
packet->bitfields2.engine_sel =
|
||||
engine_sel__mes_map_queues__compute_vi;
|
||||
packet->bitfields2.gws_control_queue = q->gws ? 1 : 0;
|
||||
packet->bitfields2.gws_control_queue = q->properties.is_gws ? 1 : 0;
|
||||
packet->bitfields2.extended_engine_sel =
|
||||
extended_engine_sel__mes_map_queues__legacy_engine_sel;
|
||||
packet->bitfields2.queue_type =
|
||||
|
|
|
|||
|
|
@ -510,6 +510,10 @@ static ssize_t node_show(struct kobject *kobj, struct attribute *attr,
|
|||
dev->node_props.capability |=
|
||||
HSA_CAP_AQL_QUEUE_DOUBLE_MAP;
|
||||
|
||||
if (KFD_GC_VERSION(dev->gpu) < IP_VERSION(10, 0, 0) &&
|
||||
(dev->gpu->adev->sdma.supported_reset & AMDGPU_RESET_TYPE_PER_QUEUE))
|
||||
dev->node_props.capability2 |= HSA_CAP2_PER_SDMA_QUEUE_RESET_SUPPORTED;
|
||||
|
||||
sysfs_show_32bit_prop(buffer, offs, "max_engine_clk_fcompute",
|
||||
dev->node_props.max_engine_clk_fcompute);
|
||||
|
||||
|
|
@ -2008,8 +2012,6 @@ static void kfd_topology_set_capabilities(struct kfd_topology_device *dev)
|
|||
if (!amdgpu_sriov_vf(dev->gpu->adev))
|
||||
dev->node_props.capability |= HSA_CAP_PER_QUEUE_RESET_SUPPORTED;
|
||||
|
||||
if (dev->gpu->adev->sdma.supported_reset & AMDGPU_RESET_TYPE_PER_QUEUE)
|
||||
dev->node_props.capability2 |= HSA_CAP2_PER_SDMA_QUEUE_RESET_SUPPORTED;
|
||||
} else {
|
||||
dev->node_props.debug_prop |= HSA_DBG_WATCH_ADDR_MASK_LO_BIT_GFX10 |
|
||||
HSA_DBG_WATCH_ADDR_MASK_HI_BIT;
|
||||
|
|
|
|||
|
|
@ -4718,9 +4718,23 @@ static int get_brightness_range(const struct amdgpu_dm_backlight_caps *caps,
|
|||
return 1;
|
||||
}
|
||||
|
||||
static void convert_custom_brightness(const struct amdgpu_dm_backlight_caps *caps,
|
||||
uint32_t *brightness)
|
||||
/* Rescale from [min..max] to [0..AMDGPU_MAX_BL_LEVEL] */
|
||||
static inline u32 scale_input_to_fw(int min, int max, u64 input)
|
||||
{
|
||||
return DIV_ROUND_CLOSEST_ULL(input * AMDGPU_MAX_BL_LEVEL, max - min);
|
||||
}
|
||||
|
||||
/* Rescale from [0..AMDGPU_MAX_BL_LEVEL] to [min..max] */
|
||||
static inline u32 scale_fw_to_input(int min, int max, u64 input)
|
||||
{
|
||||
return min + DIV_ROUND_CLOSEST_ULL(input * (max - min), AMDGPU_MAX_BL_LEVEL);
|
||||
}
|
||||
|
||||
static void convert_custom_brightness(const struct amdgpu_dm_backlight_caps *caps,
|
||||
unsigned int min, unsigned int max,
|
||||
uint32_t *user_brightness)
|
||||
{
|
||||
u32 brightness = scale_input_to_fw(min, max, *user_brightness);
|
||||
u8 prev_signal = 0, prev_lum = 0;
|
||||
int i = 0;
|
||||
|
||||
|
|
@ -4731,7 +4745,7 @@ static void convert_custom_brightness(const struct amdgpu_dm_backlight_caps *cap
|
|||
return;
|
||||
|
||||
/* choose start to run less interpolation steps */
|
||||
if (caps->luminance_data[caps->data_points/2].input_signal > *brightness)
|
||||
if (caps->luminance_data[caps->data_points/2].input_signal > brightness)
|
||||
i = caps->data_points/2;
|
||||
do {
|
||||
u8 signal = caps->luminance_data[i].input_signal;
|
||||
|
|
@ -4742,17 +4756,18 @@ static void convert_custom_brightness(const struct amdgpu_dm_backlight_caps *cap
|
|||
* brightness < signal: interpolate between previous and current luminance numerator
|
||||
* brightness > signal: find next data point
|
||||
*/
|
||||
if (*brightness > signal) {
|
||||
if (brightness > signal) {
|
||||
prev_signal = signal;
|
||||
prev_lum = lum;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (*brightness < signal)
|
||||
if (brightness < signal)
|
||||
lum = prev_lum + DIV_ROUND_CLOSEST((lum - prev_lum) *
|
||||
(*brightness - prev_signal),
|
||||
(brightness - prev_signal),
|
||||
signal - prev_signal);
|
||||
*brightness = DIV_ROUND_CLOSEST(lum * *brightness, 101);
|
||||
*user_brightness = scale_fw_to_input(min, max,
|
||||
DIV_ROUND_CLOSEST(lum * brightness, 101));
|
||||
return;
|
||||
} while (i < caps->data_points);
|
||||
}
|
||||
|
|
@ -4765,11 +4780,10 @@ static u32 convert_brightness_from_user(const struct amdgpu_dm_backlight_caps *c
|
|||
if (!get_brightness_range(caps, &min, &max))
|
||||
return brightness;
|
||||
|
||||
convert_custom_brightness(caps, &brightness);
|
||||
convert_custom_brightness(caps, min, max, &brightness);
|
||||
|
||||
// Rescale 0..255 to min..max
|
||||
return min + DIV_ROUND_CLOSEST((max - min) * brightness,
|
||||
AMDGPU_MAX_BL_LEVEL);
|
||||
// Rescale 0..max to min..max
|
||||
return min + DIV_ROUND_CLOSEST_ULL((u64)(max - min) * brightness, max);
|
||||
}
|
||||
|
||||
static u32 convert_brightness_to_user(const struct amdgpu_dm_backlight_caps *caps,
|
||||
|
|
@ -4782,8 +4796,8 @@ static u32 convert_brightness_to_user(const struct amdgpu_dm_backlight_caps *cap
|
|||
|
||||
if (brightness < min)
|
||||
return 0;
|
||||
// Rescale min..max to 0..255
|
||||
return DIV_ROUND_CLOSEST(AMDGPU_MAX_BL_LEVEL * (brightness - min),
|
||||
// Rescale min..max to 0..max
|
||||
return DIV_ROUND_CLOSEST_ULL((u64)max * (brightness - min),
|
||||
max - min);
|
||||
}
|
||||
|
||||
|
|
@ -4908,7 +4922,7 @@ amdgpu_dm_register_backlight_device(struct amdgpu_dm_connector *aconnector)
|
|||
struct drm_device *drm = aconnector->base.dev;
|
||||
struct amdgpu_display_manager *dm = &drm_to_adev(drm)->dm;
|
||||
struct backlight_properties props = { 0 };
|
||||
struct amdgpu_dm_backlight_caps caps = { 0 };
|
||||
struct amdgpu_dm_backlight_caps *caps;
|
||||
char bl_name[16];
|
||||
int min, max;
|
||||
|
||||
|
|
@ -4922,22 +4936,21 @@ amdgpu_dm_register_backlight_device(struct amdgpu_dm_connector *aconnector)
|
|||
return;
|
||||
}
|
||||
|
||||
amdgpu_acpi_get_backlight_caps(&caps);
|
||||
if (caps.caps_valid && get_brightness_range(&caps, &min, &max)) {
|
||||
caps = &dm->backlight_caps[aconnector->bl_idx];
|
||||
if (get_brightness_range(caps, &min, &max)) {
|
||||
if (power_supply_is_system_supplied() > 0)
|
||||
props.brightness = (max - min) * DIV_ROUND_CLOSEST(caps.ac_level, 100);
|
||||
props.brightness = (max - min) * DIV_ROUND_CLOSEST(caps->ac_level, 100);
|
||||
else
|
||||
props.brightness = (max - min) * DIV_ROUND_CLOSEST(caps.dc_level, 100);
|
||||
props.brightness = (max - min) * DIV_ROUND_CLOSEST(caps->dc_level, 100);
|
||||
/* min is zero, so max needs to be adjusted */
|
||||
props.max_brightness = max - min;
|
||||
drm_dbg(drm, "Backlight caps: min: %d, max: %d, ac %d, dc %d\n", min, max,
|
||||
caps.ac_level, caps.dc_level);
|
||||
caps->ac_level, caps->dc_level);
|
||||
} else
|
||||
props.brightness = AMDGPU_MAX_BL_LEVEL;
|
||||
props.brightness = props.max_brightness = AMDGPU_MAX_BL_LEVEL;
|
||||
|
||||
if (caps.data_points && !(amdgpu_dc_debug_mask & DC_DISABLE_CUSTOM_BRIGHTNESS_CURVE))
|
||||
if (caps->data_points && !(amdgpu_dc_debug_mask & DC_DISABLE_CUSTOM_BRIGHTNESS_CURVE))
|
||||
drm_info(drm, "Using custom brightness curve\n");
|
||||
props.max_brightness = AMDGPU_MAX_BL_LEVEL;
|
||||
props.type = BACKLIGHT_RAW;
|
||||
|
||||
snprintf(bl_name, sizeof(bl_name), "amdgpu_bl%d",
|
||||
|
|
|
|||
|
|
@ -241,6 +241,7 @@ static bool create_links(
|
|||
DC_LOG_DC("BIOS object table - end");
|
||||
|
||||
/* Create a link for each usb4 dpia port */
|
||||
dc->lowest_dpia_link_index = MAX_LINKS;
|
||||
for (i = 0; i < dc->res_pool->usb4_dpia_count; i++) {
|
||||
struct link_init_data link_init_params = {0};
|
||||
struct dc_link *link;
|
||||
|
|
@ -253,6 +254,9 @@ static bool create_links(
|
|||
|
||||
link = dc->link_srv->create_link(&link_init_params);
|
||||
if (link) {
|
||||
if (dc->lowest_dpia_link_index > dc->link_count)
|
||||
dc->lowest_dpia_link_index = dc->link_count;
|
||||
|
||||
dc->links[dc->link_count] = link;
|
||||
link->dc = dc;
|
||||
++dc->link_count;
|
||||
|
|
@ -6376,6 +6380,35 @@ unsigned int dc_get_det_buffer_size_from_state(const struct dc_state *context)
|
|||
else
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
***********************************************************************************************
|
||||
* dc_get_host_router_index: Get index of host router from a dpia link
|
||||
*
|
||||
* This function return a host router index of the target link. If the target link is dpia link.
|
||||
*
|
||||
* @param [in] link: target link
|
||||
* @param [out] host_router_index: host router index of the target link
|
||||
*
|
||||
* @return: true if the host router index is found and valid.
|
||||
*
|
||||
***********************************************************************************************
|
||||
*/
|
||||
bool dc_get_host_router_index(const struct dc_link *link, unsigned int *host_router_index)
|
||||
{
|
||||
struct dc *dc = link->ctx->dc;
|
||||
|
||||
if (link->ep_type != DISPLAY_ENDPOINT_USB4_DPIA)
|
||||
return false;
|
||||
|
||||
if (link->link_index < dc->lowest_dpia_link_index)
|
||||
return false;
|
||||
|
||||
*host_router_index = (link->link_index - dc->lowest_dpia_link_index) / dc->caps.num_of_dpias_per_host_router;
|
||||
if (*host_router_index < dc->caps.num_of_host_routers)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool dc_is_cursor_limit_pending(struct dc *dc)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -66,7 +66,8 @@ struct dmub_notification;
|
|||
#define MAX_STREAMS 6
|
||||
#define MIN_VIEWPORT_SIZE 12
|
||||
#define MAX_NUM_EDP 2
|
||||
#define MAX_HOST_ROUTERS_NUM 2
|
||||
#define MAX_HOST_ROUTERS_NUM 3
|
||||
#define MAX_DPIA_PER_HOST_ROUTER 2
|
||||
|
||||
/* Display Core Interfaces */
|
||||
struct dc_versions {
|
||||
|
|
@ -305,6 +306,8 @@ struct dc_caps {
|
|||
/* Conservative limit for DCC cases which require ODM4:1 to support*/
|
||||
uint32_t dcc_plane_width_limit;
|
||||
struct dc_scl_caps scl_caps;
|
||||
uint8_t num_of_host_routers;
|
||||
uint8_t num_of_dpias_per_host_router;
|
||||
};
|
||||
|
||||
struct dc_bug_wa {
|
||||
|
|
@ -1603,6 +1606,7 @@ struct dc {
|
|||
|
||||
uint8_t link_count;
|
||||
struct dc_link *links[MAX_LINKS];
|
||||
uint8_t lowest_dpia_link_index;
|
||||
struct link_service *link_srv;
|
||||
|
||||
struct dc_state *current_state;
|
||||
|
|
@ -2595,6 +2599,8 @@ struct dc_power_profile dc_get_power_profile_for_dc_state(const struct dc_state
|
|||
|
||||
unsigned int dc_get_det_buffer_size_from_state(const struct dc_state *context);
|
||||
|
||||
bool dc_get_host_router_index(const struct dc_link *link, unsigned int *host_router_index);
|
||||
|
||||
/* DSC Interfaces */
|
||||
#include "dc_dsc.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -1172,8 +1172,8 @@ struct dc_lttpr_caps {
|
|||
union dp_128b_132b_supported_lttpr_link_rates supported_128b_132b_rates;
|
||||
union dp_alpm_lttpr_cap alpm;
|
||||
uint8_t aux_rd_interval[MAX_REPEATER_CNT - 1];
|
||||
uint8_t lttpr_ieee_oui[3];
|
||||
uint8_t lttpr_device_id[6];
|
||||
uint8_t lttpr_ieee_oui[3]; // Always read from closest LTTPR to host
|
||||
uint8_t lttpr_device_id[6]; // Always read from closest LTTPR to host
|
||||
};
|
||||
|
||||
struct dc_dongle_dfp_cap_ext {
|
||||
|
|
|
|||
|
|
@ -788,6 +788,7 @@ static void populate_dml21_plane_config_from_plane_state(struct dml2_context *dm
|
|||
plane->pixel_format = dml2_420_10;
|
||||
break;
|
||||
case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
|
||||
case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616:
|
||||
case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
|
||||
case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
|
||||
plane->pixel_format = dml2_444_64;
|
||||
|
|
|
|||
|
|
@ -4685,7 +4685,10 @@ static void calculate_tdlut_setting(
|
|||
//the tdlut is fetched during the 2 row times of prefetch.
|
||||
if (p->setup_for_tdlut) {
|
||||
*p->tdlut_groups_per_2row_ub = (unsigned int)math_ceil2((double) *p->tdlut_bytes_per_frame / *p->tdlut_bytes_per_group, 1);
|
||||
*p->tdlut_opt_time = (*p->tdlut_bytes_per_frame - p->cursor_buffer_size * 1024) / tdlut_drain_rate;
|
||||
if (*p->tdlut_bytes_per_frame > p->cursor_buffer_size * 1024)
|
||||
*p->tdlut_opt_time = (*p->tdlut_bytes_per_frame - p->cursor_buffer_size * 1024) / tdlut_drain_rate;
|
||||
else
|
||||
*p->tdlut_opt_time = 0;
|
||||
*p->tdlut_drain_time = p->cursor_buffer_size * 1024 / tdlut_drain_rate;
|
||||
*p->tdlut_bytes_to_deliver = (unsigned int) (p->cursor_buffer_size * 1024.0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -953,6 +953,7 @@ static void populate_dml_surface_cfg_from_plane_state(enum dml_project_id dml2_p
|
|||
out->SourcePixelFormat[location] = dml_420_10;
|
||||
break;
|
||||
case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
|
||||
case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616:
|
||||
case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
|
||||
case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
|
||||
out->SourcePixelFormat[location] = dml_444_64;
|
||||
|
|
|
|||
|
|
@ -1225,7 +1225,7 @@ void dce110_blank_stream(struct pipe_ctx *pipe_ctx)
|
|||
return;
|
||||
|
||||
if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) {
|
||||
if (!link->skip_implict_edp_power_control)
|
||||
if (!link->skip_implict_edp_power_control && hws)
|
||||
hws->funcs.edp_backlight_control(link, false);
|
||||
link->dc->hwss.set_abm_immediate_disable(pipe_ctx);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1047,6 +1047,15 @@ void dcn35_calc_blocks_to_gate(struct dc *dc, struct dc_state *context,
|
|||
if (dc->caps.sequential_ono) {
|
||||
update_state->pg_pipe_res_update[PG_HUBP][pipe_ctx->stream_res.dsc->inst] = false;
|
||||
update_state->pg_pipe_res_update[PG_DPP][pipe_ctx->stream_res.dsc->inst] = false;
|
||||
|
||||
/* All HUBP/DPP instances must be powered if the DSC inst != HUBP inst */
|
||||
if (!pipe_ctx->top_pipe && pipe_ctx->plane_res.hubp &&
|
||||
pipe_ctx->plane_res.hubp->inst != pipe_ctx->stream_res.dsc->inst) {
|
||||
for (j = 0; j < dc->res_pool->pipe_count; ++j) {
|
||||
update_state->pg_pipe_res_update[PG_HUBP][j] = false;
|
||||
update_state->pg_pipe_res_update[PG_DPP][j] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1193,6 +1202,25 @@ void dcn35_calc_blocks_to_ungate(struct dc *dc, struct dc_state *context,
|
|||
update_state->pg_pipe_res_update[PG_HDMISTREAM][0] = true;
|
||||
|
||||
if (dc->caps.sequential_ono) {
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct pipe_ctx *new_pipe = &context->res_ctx.pipe_ctx[i];
|
||||
|
||||
if (new_pipe->stream_res.dsc && !new_pipe->top_pipe &&
|
||||
update_state->pg_pipe_res_update[PG_DSC][new_pipe->stream_res.dsc->inst]) {
|
||||
update_state->pg_pipe_res_update[PG_HUBP][new_pipe->stream_res.dsc->inst] = true;
|
||||
update_state->pg_pipe_res_update[PG_DPP][new_pipe->stream_res.dsc->inst] = true;
|
||||
|
||||
/* All HUBP/DPP instances must be powered if the DSC inst != HUBP inst */
|
||||
if (new_pipe->plane_res.hubp &&
|
||||
new_pipe->plane_res.hubp->inst != new_pipe->stream_res.dsc->inst) {
|
||||
for (j = 0; j < dc->res_pool->pipe_count; ++j) {
|
||||
update_state->pg_pipe_res_update[PG_HUBP][j] = true;
|
||||
update_state->pg_pipe_res_update[PG_DPP][j] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) {
|
||||
if (update_state->pg_pipe_res_update[PG_HUBP][i] &&
|
||||
update_state->pg_pipe_res_update[PG_DPP][i]) {
|
||||
|
|
|
|||
|
|
@ -385,9 +385,15 @@ bool dp_is_128b_132b_signal(struct pipe_ctx *pipe_ctx)
|
|||
bool dp_is_lttpr_present(struct dc_link *link)
|
||||
{
|
||||
/* Some sink devices report invalid LTTPR revision, so don't validate against that cap */
|
||||
return (dp_parse_lttpr_repeater_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) != 0 &&
|
||||
uint32_t lttpr_count = dp_parse_lttpr_repeater_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
|
||||
bool is_lttpr_present = (lttpr_count > 0 &&
|
||||
link->dpcd_caps.lttpr_caps.max_lane_count > 0 &&
|
||||
link->dpcd_caps.lttpr_caps.max_lane_count <= 4);
|
||||
|
||||
if (lttpr_count > 0 && !is_lttpr_present)
|
||||
DC_LOG_ERROR("LTTPR count is nonzero but invalid lane count reported. Assuming no LTTPR present.\n");
|
||||
|
||||
return is_lttpr_present;
|
||||
}
|
||||
|
||||
/* in DP compliance test, DPR-120 may have
|
||||
|
|
@ -1551,6 +1557,8 @@ enum dc_status dp_retrieve_lttpr_cap(struct dc_link *link)
|
|||
uint8_t lttpr_dpcd_data[10] = {0};
|
||||
enum dc_status status;
|
||||
bool is_lttpr_present;
|
||||
uint32_t lttpr_count;
|
||||
uint32_t closest_lttpr_offset;
|
||||
|
||||
/* Logic to determine LTTPR support*/
|
||||
bool vbios_lttpr_interop = link->dc->caps.vbios_lttpr_aware;
|
||||
|
|
@ -1602,20 +1610,22 @@ enum dc_status dp_retrieve_lttpr_cap(struct dc_link *link)
|
|||
lttpr_dpcd_data[DP_LTTPR_ALPM_CAPABILITIES -
|
||||
DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
|
||||
|
||||
lttpr_count = dp_parse_lttpr_repeater_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
|
||||
|
||||
/* If this chip cap is set, at least one retimer must exist in the chain
|
||||
* Override count to 1 if we receive a known bad count (0 or an invalid value) */
|
||||
if (((link->chip_caps & AMD_EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK) == AMD_EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&
|
||||
(dp_parse_lttpr_repeater_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) == 0)) {
|
||||
lttpr_count == 0) {
|
||||
/* If you see this message consistently, either the host platform has FIXED_VS flag
|
||||
* incorrectly configured or the sink device is returning an invalid count.
|
||||
*/
|
||||
DC_LOG_ERROR("lttpr_caps phy_repeater_cnt is 0x%x, forcing it to 0x80.",
|
||||
link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
|
||||
link->dpcd_caps.lttpr_caps.phy_repeater_cnt = 0x80;
|
||||
lttpr_count = 1;
|
||||
DC_LOG_DC("lttpr_caps forced phy_repeater_cnt = %d\n", link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
|
||||
}
|
||||
|
||||
/* Attempt to train in LTTPR transparent mode if repeater count exceeds 8. */
|
||||
is_lttpr_present = dp_is_lttpr_present(link);
|
||||
|
||||
DC_LOG_DC("is_lttpr_present = %d\n", is_lttpr_present);
|
||||
|
|
@ -1623,11 +1633,25 @@ enum dc_status dp_retrieve_lttpr_cap(struct dc_link *link)
|
|||
if (is_lttpr_present) {
|
||||
CONN_DATA_DETECT(link, lttpr_dpcd_data, sizeof(lttpr_dpcd_data), "LTTPR Caps: ");
|
||||
|
||||
core_link_read_dpcd(link, DP_LTTPR_IEEE_OUI, link->dpcd_caps.lttpr_caps.lttpr_ieee_oui, sizeof(link->dpcd_caps.lttpr_caps.lttpr_ieee_oui));
|
||||
CONN_DATA_DETECT(link, link->dpcd_caps.lttpr_caps.lttpr_ieee_oui, sizeof(link->dpcd_caps.lttpr_caps.lttpr_ieee_oui), "LTTPR IEEE OUI: ");
|
||||
// Identify closest LTTPR to determine if workarounds required for known embedded LTTPR
|
||||
closest_lttpr_offset = dp_get_closest_lttpr_offset(lttpr_count);
|
||||
|
||||
core_link_read_dpcd(link, DP_LTTPR_DEVICE_ID, link->dpcd_caps.lttpr_caps.lttpr_device_id, sizeof(link->dpcd_caps.lttpr_caps.lttpr_device_id));
|
||||
CONN_DATA_DETECT(link, link->dpcd_caps.lttpr_caps.lttpr_device_id, sizeof(link->dpcd_caps.lttpr_caps.lttpr_device_id), "LTTPR Device ID: ");
|
||||
core_link_read_dpcd(link, (DP_LTTPR_IEEE_OUI + closest_lttpr_offset),
|
||||
link->dpcd_caps.lttpr_caps.lttpr_ieee_oui, sizeof(link->dpcd_caps.lttpr_caps.lttpr_ieee_oui));
|
||||
core_link_read_dpcd(link, (DP_LTTPR_DEVICE_ID + closest_lttpr_offset),
|
||||
link->dpcd_caps.lttpr_caps.lttpr_device_id, sizeof(link->dpcd_caps.lttpr_caps.lttpr_device_id));
|
||||
|
||||
if (lttpr_count > 1) {
|
||||
CONN_DATA_DETECT(link, link->dpcd_caps.lttpr_caps.lttpr_ieee_oui, sizeof(link->dpcd_caps.lttpr_caps.lttpr_ieee_oui),
|
||||
"Closest LTTPR To Host's IEEE OUI: ");
|
||||
CONN_DATA_DETECT(link, link->dpcd_caps.lttpr_caps.lttpr_device_id, sizeof(link->dpcd_caps.lttpr_caps.lttpr_device_id),
|
||||
"Closest LTTPR To Host's LTTPR Device ID: ");
|
||||
} else {
|
||||
CONN_DATA_DETECT(link, link->dpcd_caps.lttpr_caps.lttpr_ieee_oui, sizeof(link->dpcd_caps.lttpr_caps.lttpr_ieee_oui),
|
||||
"LTTPR IEEE OUI: ");
|
||||
CONN_DATA_DETECT(link, link->dpcd_caps.lttpr_caps.lttpr_device_id, sizeof(link->dpcd_caps.lttpr_caps.lttpr_device_id),
|
||||
"LTTPR Device ID: ");
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
|
|
|
|||
|
|
@ -1954,6 +1954,9 @@ static bool dcn31_resource_construct(
|
|||
dc->caps.color.mpc.ogam_rom_caps.hlg = 0;
|
||||
dc->caps.color.mpc.ocsc = 1;
|
||||
|
||||
dc->caps.num_of_host_routers = 2;
|
||||
dc->caps.num_of_dpias_per_host_router = 2;
|
||||
|
||||
/* Use pipe context based otg sync logic */
|
||||
dc->config.use_pipe_ctx_sync_logic = true;
|
||||
dc->config.disable_hbr_audio_dp2 = true;
|
||||
|
|
|
|||
|
|
@ -1885,6 +1885,9 @@ static bool dcn314_resource_construct(
|
|||
|
||||
dc->caps.max_disp_clock_khz_at_vmin = 650000;
|
||||
|
||||
dc->caps.num_of_host_routers = 2;
|
||||
dc->caps.num_of_dpias_per_host_router = 2;
|
||||
|
||||
/* Use pipe context based otg sync logic */
|
||||
dc->config.use_pipe_ctx_sync_logic = true;
|
||||
|
||||
|
|
|
|||
|
|
@ -1894,6 +1894,9 @@ static bool dcn35_resource_construct(
|
|||
dc->caps.color.mpc.ogam_rom_caps.hlg = 0;
|
||||
dc->caps.color.mpc.ocsc = 1;
|
||||
|
||||
dc->caps.num_of_host_routers = 2;
|
||||
dc->caps.num_of_dpias_per_host_router = 2;
|
||||
|
||||
/* max_disp_clock_khz_at_vmin is slightly lower than the STA value in order
|
||||
* to provide some margin.
|
||||
* It's expected for furture ASIC to have equal or higher value, in order to
|
||||
|
|
|
|||
|
|
@ -1866,6 +1866,9 @@ static bool dcn351_resource_construct(
|
|||
dc->caps.color.mpc.ogam_rom_caps.hlg = 0;
|
||||
dc->caps.color.mpc.ocsc = 1;
|
||||
|
||||
dc->caps.num_of_host_routers = 2;
|
||||
dc->caps.num_of_dpias_per_host_router = 2;
|
||||
|
||||
/* max_disp_clock_khz_at_vmin is slightly lower than the STA value in order
|
||||
* to provide some margin.
|
||||
* It's expected for furture ASIC to have equal or higher value, in order to
|
||||
|
|
|
|||
|
|
@ -1867,6 +1867,9 @@ static bool dcn36_resource_construct(
|
|||
dc->caps.color.mpc.ogam_rom_caps.hlg = 0;
|
||||
dc->caps.color.mpc.ocsc = 1;
|
||||
|
||||
dc->caps.num_of_host_routers = 2;
|
||||
dc->caps.num_of_dpias_per_host_router = 2;
|
||||
|
||||
/* max_disp_clock_khz_at_vmin is slightly lower than the STA value in order
|
||||
* to provide some margin.
|
||||
* It's expected for furture ASIC to have equal or higher value, in order to
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@
|
|||
|
||||
MODULE_FIRMWARE("amdgpu/aldebaran_smc.bin");
|
||||
MODULE_FIRMWARE("amdgpu/smu_13_0_0.bin");
|
||||
MODULE_FIRMWARE("amdgpu/smu_13_0_0_kicker.bin");
|
||||
MODULE_FIRMWARE("amdgpu/smu_13_0_7.bin");
|
||||
MODULE_FIRMWARE("amdgpu/smu_13_0_10.bin");
|
||||
|
||||
|
|
@ -92,7 +93,7 @@ const int pmfw_decoded_link_width[7] = {0, 1, 2, 4, 8, 12, 16};
|
|||
int smu_v13_0_init_microcode(struct smu_context *smu)
|
||||
{
|
||||
struct amdgpu_device *adev = smu->adev;
|
||||
char ucode_prefix[15];
|
||||
char ucode_prefix[30];
|
||||
int err = 0;
|
||||
const struct smc_firmware_header_v1_0 *hdr;
|
||||
const struct common_firmware_header *header;
|
||||
|
|
@ -103,8 +104,13 @@ int smu_v13_0_init_microcode(struct smu_context *smu)
|
|||
return 0;
|
||||
|
||||
amdgpu_ucode_ip_version_decode(adev, MP1_HWIP, ucode_prefix, sizeof(ucode_prefix));
|
||||
err = amdgpu_ucode_request(adev, &adev->pm.fw, AMDGPU_UCODE_REQUIRED,
|
||||
"amdgpu/%s.bin", ucode_prefix);
|
||||
|
||||
if (amdgpu_is_kicker_fw(adev))
|
||||
err = amdgpu_ucode_request(adev, &adev->pm.fw, AMDGPU_UCODE_REQUIRED,
|
||||
"amdgpu/%s_kicker.bin", ucode_prefix);
|
||||
else
|
||||
err = amdgpu_ucode_request(adev, &adev->pm.fw, AMDGPU_UCODE_REQUIRED,
|
||||
"amdgpu/%s.bin", ucode_prefix);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ bool malidp_format_mod_supported(struct drm_device *drm,
|
|||
}
|
||||
|
||||
if (!fourcc_mod_is_vendor(modifier, ARM)) {
|
||||
DRM_ERROR("Unknown modifier (not Arm)\n");
|
||||
DRM_DEBUG_KMS("Unknown modifier (not Arm)\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@
|
|||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include <drm/drm_atomic.h>
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ static enum drm_gpu_sched_stat etnaviv_sched_timedout_job(struct drm_sched_job
|
|||
*sched_job)
|
||||
{
|
||||
struct etnaviv_gem_submit *submit = to_etnaviv_submit(sched_job);
|
||||
struct drm_gpu_scheduler *sched = sched_job->sched;
|
||||
struct etnaviv_gpu *gpu = submit->gpu;
|
||||
u32 dma_addr, primid = 0;
|
||||
int change;
|
||||
|
|
@ -89,7 +90,9 @@ static enum drm_gpu_sched_stat etnaviv_sched_timedout_job(struct drm_sched_job
|
|||
return DRM_GPU_SCHED_STAT_NOMINAL;
|
||||
|
||||
out_no_timeout:
|
||||
list_add(&sched_job->list, &sched_job->sched->pending_list);
|
||||
spin_lock(&sched->job_list_lock);
|
||||
list_add(&sched_job->list, &sched->pending_list);
|
||||
spin_unlock(&sched->job_list_lock);
|
||||
return DRM_GPU_SCHED_STAT_NOMINAL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1056,7 +1056,7 @@ static void bxt_dsi_get_pipe_config(struct intel_encoder *encoder,
|
|||
BXT_MIPI_TRANS_VACTIVE(port));
|
||||
adjusted_mode->crtc_vtotal =
|
||||
intel_de_read(display,
|
||||
BXT_MIPI_TRANS_VTOTAL(port));
|
||||
BXT_MIPI_TRANS_VTOTAL(port)) + 1;
|
||||
|
||||
hactive = adjusted_mode->crtc_hdisplay;
|
||||
hfp = intel_de_read(display, MIPI_HFP_COUNT(display, port));
|
||||
|
|
@ -1260,7 +1260,7 @@ static void set_dsi_timings(struct intel_encoder *encoder,
|
|||
intel_de_write(display, BXT_MIPI_TRANS_VACTIVE(port),
|
||||
adjusted_mode->crtc_vdisplay);
|
||||
intel_de_write(display, BXT_MIPI_TRANS_VTOTAL(port),
|
||||
adjusted_mode->crtc_vtotal);
|
||||
adjusted_mode->crtc_vtotal - 1);
|
||||
}
|
||||
|
||||
intel_de_write(display, MIPI_HACTIVE_AREA_COUNT(display, port),
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ static u32 config_mask(const u64 config)
|
|||
{
|
||||
unsigned int bit = config_bit(config);
|
||||
|
||||
if (__builtin_constant_p(config))
|
||||
if (__builtin_constant_p(bit))
|
||||
BUILD_BUG_ON(bit >
|
||||
BITS_PER_TYPE(typeof_member(struct i915_pmu,
|
||||
enable)) - 1);
|
||||
|
|
@ -121,7 +121,7 @@ static u32 config_mask(const u64 config)
|
|||
BITS_PER_TYPE(typeof_member(struct i915_pmu,
|
||||
enable)) - 1);
|
||||
|
||||
return BIT(config_bit(config));
|
||||
return BIT(bit);
|
||||
}
|
||||
|
||||
static bool is_engine_event(struct perf_event *event)
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@
|
|||
* Authors: Dave Airlie <airlied@redhat.com>
|
||||
*/
|
||||
|
||||
#include <linux/export.h>
|
||||
#include <linux/i2c-algo-bit.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/pci.h>
|
||||
|
|
|
|||
|
|
@ -71,10 +71,6 @@ static int a2xx_gpummu_unmap(struct msm_mmu *mmu, uint64_t iova, size_t len)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void a2xx_gpummu_resume_translation(struct msm_mmu *mmu)
|
||||
{
|
||||
}
|
||||
|
||||
static void a2xx_gpummu_destroy(struct msm_mmu *mmu)
|
||||
{
|
||||
struct a2xx_gpummu *gpummu = to_a2xx_gpummu(mmu);
|
||||
|
|
@ -90,7 +86,6 @@ static const struct msm_mmu_funcs funcs = {
|
|||
.map = a2xx_gpummu_map,
|
||||
.unmap = a2xx_gpummu_unmap,
|
||||
.destroy = a2xx_gpummu_destroy,
|
||||
.resume_translation = a2xx_gpummu_resume_translation,
|
||||
};
|
||||
|
||||
struct msm_mmu *a2xx_gpummu_new(struct device *dev, struct msm_gpu *gpu)
|
||||
|
|
|
|||
|
|
@ -131,6 +131,8 @@ static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
|
|||
struct msm_ringbuffer *ring = submit->ring;
|
||||
unsigned int i, ibs = 0;
|
||||
|
||||
adreno_check_and_reenable_stall(adreno_gpu);
|
||||
|
||||
if (IS_ENABLED(CONFIG_DRM_MSM_GPU_SUDO) && submit->in_rb) {
|
||||
ring->cur_ctx_seqno = 0;
|
||||
a5xx_submit_in_rb(gpu, submit);
|
||||
|
|
|
|||
|
|
@ -130,6 +130,20 @@ static void a6xx_set_pagetable(struct a6xx_gpu *a6xx_gpu,
|
|||
OUT_RING(ring, lower_32_bits(rbmemptr(ring, fence)));
|
||||
OUT_RING(ring, upper_32_bits(rbmemptr(ring, fence)));
|
||||
OUT_RING(ring, submit->seqno - 1);
|
||||
|
||||
OUT_PKT7(ring, CP_THREAD_CONTROL, 1);
|
||||
OUT_RING(ring, CP_SET_THREAD_BOTH);
|
||||
|
||||
/* Reset state used to synchronize BR and BV */
|
||||
OUT_PKT7(ring, CP_RESET_CONTEXT_STATE, 1);
|
||||
OUT_RING(ring,
|
||||
CP_RESET_CONTEXT_STATE_0_CLEAR_ON_CHIP_TS |
|
||||
CP_RESET_CONTEXT_STATE_0_CLEAR_RESOURCE_TABLE |
|
||||
CP_RESET_CONTEXT_STATE_0_CLEAR_BV_BR_COUNTER |
|
||||
CP_RESET_CONTEXT_STATE_0_RESET_GLOBAL_LOCAL_TS);
|
||||
|
||||
OUT_PKT7(ring, CP_THREAD_CONTROL, 1);
|
||||
OUT_RING(ring, CP_SET_THREAD_BR);
|
||||
}
|
||||
|
||||
if (!sysprof) {
|
||||
|
|
@ -212,6 +226,8 @@ static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
|
|||
struct msm_ringbuffer *ring = submit->ring;
|
||||
unsigned int i, ibs = 0;
|
||||
|
||||
adreno_check_and_reenable_stall(adreno_gpu);
|
||||
|
||||
a6xx_set_pagetable(a6xx_gpu, ring, submit);
|
||||
|
||||
get_stats_counter(ring, REG_A6XX_RBBM_PERFCTR_CP(0),
|
||||
|
|
@ -335,6 +351,8 @@ static void a7xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
|
|||
struct msm_ringbuffer *ring = submit->ring;
|
||||
unsigned int i, ibs = 0;
|
||||
|
||||
adreno_check_and_reenable_stall(adreno_gpu);
|
||||
|
||||
/*
|
||||
* Toggle concurrent binning for pagetable switch and set the thread to
|
||||
* BR since only it can execute the pagetable switch packets.
|
||||
|
|
|
|||
|
|
@ -137,9 +137,8 @@ struct msm_gpu *adreno_load_gpu(struct drm_device *dev)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static int find_chipid(struct device *dev, uint32_t *chipid)
|
||||
static int find_chipid(struct device_node *node, uint32_t *chipid)
|
||||
{
|
||||
struct device_node *node = dev->of_node;
|
||||
const char *compat;
|
||||
int ret;
|
||||
|
||||
|
|
@ -173,15 +172,36 @@ static int find_chipid(struct device *dev, uint32_t *chipid)
|
|||
/* and if that fails, fall back to legacy "qcom,chipid" property: */
|
||||
ret = of_property_read_u32(node, "qcom,chipid", chipid);
|
||||
if (ret) {
|
||||
DRM_DEV_ERROR(dev, "could not parse qcom,chipid: %d\n", ret);
|
||||
DRM_ERROR("%pOF: could not parse qcom,chipid: %d\n",
|
||||
node, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dev_warn(dev, "Using legacy qcom,chipid binding!\n");
|
||||
pr_warn("%pOF: Using legacy qcom,chipid binding!\n", node);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool adreno_has_gpu(struct device_node *node)
|
||||
{
|
||||
const struct adreno_info *info;
|
||||
uint32_t chip_id;
|
||||
int ret;
|
||||
|
||||
ret = find_chipid(node, &chip_id);
|
||||
if (ret)
|
||||
return false;
|
||||
|
||||
info = adreno_info(chip_id);
|
||||
if (!info) {
|
||||
pr_warn("%pOF: Unknown GPU revision: %"ADRENO_CHIPID_FMT"\n",
|
||||
node, ADRENO_CHIPID_ARGS(chip_id));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int adreno_bind(struct device *dev, struct device *master, void *data)
|
||||
{
|
||||
static struct adreno_platform_config config = {};
|
||||
|
|
@ -191,19 +211,18 @@ static int adreno_bind(struct device *dev, struct device *master, void *data)
|
|||
struct msm_gpu *gpu;
|
||||
int ret;
|
||||
|
||||
ret = find_chipid(dev, &config.chip_id);
|
||||
if (ret)
|
||||
ret = find_chipid(dev->of_node, &config.chip_id);
|
||||
/* We shouldn't have gotten this far if we can't parse the chip_id */
|
||||
if (WARN_ON(ret))
|
||||
return ret;
|
||||
|
||||
dev->platform_data = &config;
|
||||
priv->gpu_pdev = to_platform_device(dev);
|
||||
|
||||
info = adreno_info(config.chip_id);
|
||||
if (!info) {
|
||||
dev_warn(drm->dev, "Unknown GPU revision: %"ADRENO_CHIPID_FMT"\n",
|
||||
ADRENO_CHIPID_ARGS(config.chip_id));
|
||||
/* We shouldn't have gotten this far if we don't recognize the GPU: */
|
||||
if (WARN_ON(!info))
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
config.info = info;
|
||||
|
||||
|
|
|
|||
|
|
@ -259,24 +259,54 @@ u64 adreno_private_address_space_size(struct msm_gpu *gpu)
|
|||
return BIT(ttbr1_cfg->ias) - ADRENO_VM_START;
|
||||
}
|
||||
|
||||
void adreno_check_and_reenable_stall(struct adreno_gpu *adreno_gpu)
|
||||
{
|
||||
struct msm_gpu *gpu = &adreno_gpu->base;
|
||||
struct msm_drm_private *priv = gpu->dev->dev_private;
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* Wait until the cooldown period has passed and we would actually
|
||||
* collect a crashdump to re-enable stall-on-fault.
|
||||
*/
|
||||
spin_lock_irqsave(&priv->fault_stall_lock, flags);
|
||||
if (!priv->stall_enabled &&
|
||||
ktime_after(ktime_get(), priv->stall_reenable_time) &&
|
||||
!READ_ONCE(gpu->crashstate)) {
|
||||
priv->stall_enabled = true;
|
||||
|
||||
gpu->aspace->mmu->funcs->set_stall(gpu->aspace->mmu, true);
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->fault_stall_lock, flags);
|
||||
}
|
||||
|
||||
#define ARM_SMMU_FSR_TF BIT(1)
|
||||
#define ARM_SMMU_FSR_PF BIT(3)
|
||||
#define ARM_SMMU_FSR_EF BIT(4)
|
||||
#define ARM_SMMU_FSR_SS BIT(30)
|
||||
|
||||
int adreno_fault_handler(struct msm_gpu *gpu, unsigned long iova, int flags,
|
||||
struct adreno_smmu_fault_info *info, const char *block,
|
||||
u32 scratch[4])
|
||||
{
|
||||
struct msm_drm_private *priv = gpu->dev->dev_private;
|
||||
const char *type = "UNKNOWN";
|
||||
bool do_devcoredump = info && !READ_ONCE(gpu->crashstate);
|
||||
bool do_devcoredump = info && (info->fsr & ARM_SMMU_FSR_SS) &&
|
||||
!READ_ONCE(gpu->crashstate);
|
||||
unsigned long irq_flags;
|
||||
|
||||
/*
|
||||
* If we aren't going to be resuming later from fault_worker, then do
|
||||
* it now.
|
||||
* In case there is a subsequent storm of pagefaults, disable
|
||||
* stall-on-fault for at least half a second.
|
||||
*/
|
||||
if (!do_devcoredump) {
|
||||
gpu->aspace->mmu->funcs->resume_translation(gpu->aspace->mmu);
|
||||
spin_lock_irqsave(&priv->fault_stall_lock, irq_flags);
|
||||
if (priv->stall_enabled) {
|
||||
priv->stall_enabled = false;
|
||||
|
||||
gpu->aspace->mmu->funcs->set_stall(gpu->aspace->mmu, false);
|
||||
}
|
||||
priv->stall_reenable_time = ktime_add_ms(ktime_get(), 500);
|
||||
spin_unlock_irqrestore(&priv->fault_stall_lock, irq_flags);
|
||||
|
||||
/*
|
||||
* Print a default message if we couldn't get the data from the
|
||||
|
|
@ -304,16 +334,18 @@ int adreno_fault_handler(struct msm_gpu *gpu, unsigned long iova, int flags,
|
|||
scratch[0], scratch[1], scratch[2], scratch[3]);
|
||||
|
||||
if (do_devcoredump) {
|
||||
struct msm_gpu_fault_info fault_info = {};
|
||||
|
||||
/* Turn off the hangcheck timer to keep it from bothering us */
|
||||
timer_delete(&gpu->hangcheck_timer);
|
||||
|
||||
gpu->fault_info.ttbr0 = info->ttbr0;
|
||||
gpu->fault_info.iova = iova;
|
||||
gpu->fault_info.flags = flags;
|
||||
gpu->fault_info.type = type;
|
||||
gpu->fault_info.block = block;
|
||||
fault_info.ttbr0 = info->ttbr0;
|
||||
fault_info.iova = iova;
|
||||
fault_info.flags = flags;
|
||||
fault_info.type = type;
|
||||
fault_info.block = block;
|
||||
|
||||
kthread_queue_work(gpu->worker, &gpu->fault_work);
|
||||
msm_gpu_fault_crashstate_capture(gpu, &fault_info);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -636,6 +636,8 @@ int adreno_fault_handler(struct msm_gpu *gpu, unsigned long iova, int flags,
|
|||
struct adreno_smmu_fault_info *info, const char *block,
|
||||
u32 scratch[4]);
|
||||
|
||||
void adreno_check_and_reenable_stall(struct adreno_gpu *gpu);
|
||||
|
||||
int adreno_read_speedbin(struct device *dev, u32 *speedbin);
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -94,17 +94,21 @@ static void drm_mode_to_intf_timing_params(
|
|||
timing->vsync_polarity = 0;
|
||||
}
|
||||
|
||||
/* for DP/EDP, Shift timings to align it to bottom right */
|
||||
if (phys_enc->hw_intf->cap->type == INTF_DP) {
|
||||
timing->wide_bus_en = dpu_encoder_is_widebus_enabled(phys_enc->parent);
|
||||
timing->compression_en = dpu_encoder_is_dsc_enabled(phys_enc->parent);
|
||||
|
||||
/*
|
||||
* For DP/EDP, Shift timings to align it to bottom right.
|
||||
* wide_bus_en is set for everything excluding SDM845 &
|
||||
* porch changes cause DisplayPort failure and HDMI tearing.
|
||||
*/
|
||||
if (phys_enc->hw_intf->cap->type == INTF_DP && timing->wide_bus_en) {
|
||||
timing->h_back_porch += timing->h_front_porch;
|
||||
timing->h_front_porch = 0;
|
||||
timing->v_back_porch += timing->v_front_porch;
|
||||
timing->v_front_porch = 0;
|
||||
}
|
||||
|
||||
timing->wide_bus_en = dpu_encoder_is_widebus_enabled(phys_enc->parent);
|
||||
timing->compression_en = dpu_encoder_is_dsc_enabled(phys_enc->parent);
|
||||
|
||||
/*
|
||||
* for DP, divide the horizonal parameters by 2 when
|
||||
* widebus is enabled
|
||||
|
|
|
|||
|
|
@ -128,6 +128,11 @@ static const struct msm_dp_desc msm_dp_desc_sa8775p[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
static const struct msm_dp_desc msm_dp_desc_sdm845[] = {
|
||||
{ .io_start = 0x0ae90000, .id = MSM_DP_CONTROLLER_0 },
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct msm_dp_desc msm_dp_desc_sc7180[] = {
|
||||
{ .io_start = 0x0ae90000, .id = MSM_DP_CONTROLLER_0, .wide_bus_supported = true },
|
||||
{}
|
||||
|
|
@ -180,7 +185,7 @@ static const struct of_device_id msm_dp_dt_match[] = {
|
|||
{ .compatible = "qcom,sc8180x-edp", .data = &msm_dp_desc_sc8180x },
|
||||
{ .compatible = "qcom,sc8280xp-dp", .data = &msm_dp_desc_sc8280xp },
|
||||
{ .compatible = "qcom,sc8280xp-edp", .data = &msm_dp_desc_sc8280xp },
|
||||
{ .compatible = "qcom,sdm845-dp", .data = &msm_dp_desc_sc7180 },
|
||||
{ .compatible = "qcom,sdm845-dp", .data = &msm_dp_desc_sdm845 },
|
||||
{ .compatible = "qcom,sm8350-dp", .data = &msm_dp_desc_sc7180 },
|
||||
{ .compatible = "qcom,sm8650-dp", .data = &msm_dp_desc_sm8650 },
|
||||
{ .compatible = "qcom,x1e80100-dp", .data = &msm_dp_desc_x1e80100 },
|
||||
|
|
|
|||
|
|
@ -704,6 +704,13 @@ static int dsi_pll_10nm_init(struct msm_dsi_phy *phy)
|
|||
/* TODO: Remove this when we have proper display handover support */
|
||||
msm_dsi_phy_pll_save_state(phy);
|
||||
|
||||
/*
|
||||
* Store also proper vco_current_rate, because its value will be used in
|
||||
* dsi_10nm_pll_restore_state().
|
||||
*/
|
||||
if (!dsi_pll_10nm_vco_recalc_rate(&pll_10nm->clk_hw, VCO_REF_CLK_RATE))
|
||||
pll_10nm->vco_current_rate = pll_10nm->phy->cfg->min_pll_rate;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -208,6 +208,35 @@ DEFINE_DEBUGFS_ATTRIBUTE(shrink_fops,
|
|||
shrink_get, shrink_set,
|
||||
"0x%08llx\n");
|
||||
|
||||
/*
|
||||
* Return the number of microseconds to wait until stall-on-fault is
|
||||
* re-enabled. If 0 then it is already enabled or will be re-enabled on the
|
||||
* next submit (unless there's a leftover devcoredump). This is useful for
|
||||
* kernel tests that intentionally produce a fault and check the devcoredump to
|
||||
* wait until the cooldown period is over.
|
||||
*/
|
||||
|
||||
static int
|
||||
stall_reenable_time_get(void *data, u64 *val)
|
||||
{
|
||||
struct msm_drm_private *priv = data;
|
||||
unsigned long irq_flags;
|
||||
|
||||
spin_lock_irqsave(&priv->fault_stall_lock, irq_flags);
|
||||
|
||||
if (priv->stall_enabled)
|
||||
*val = 0;
|
||||
else
|
||||
*val = max(ktime_us_delta(priv->stall_reenable_time, ktime_get()), 0);
|
||||
|
||||
spin_unlock_irqrestore(&priv->fault_stall_lock, irq_flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(stall_reenable_time_fops,
|
||||
stall_reenable_time_get, NULL,
|
||||
"%lld\n");
|
||||
|
||||
static int msm_gem_show(struct seq_file *m, void *arg)
|
||||
{
|
||||
|
|
@ -319,6 +348,9 @@ static void msm_debugfs_gpu_init(struct drm_minor *minor)
|
|||
debugfs_create_bool("disable_err_irq", 0600, minor->debugfs_root,
|
||||
&priv->disable_err_irq);
|
||||
|
||||
debugfs_create_file("stall_reenable_time_us", 0400, minor->debugfs_root,
|
||||
priv, &stall_reenable_time_fops);
|
||||
|
||||
gpu_devfreq = debugfs_create_dir("devfreq", minor->debugfs_root);
|
||||
|
||||
debugfs_create_bool("idle_clamp",0600, gpu_devfreq,
|
||||
|
|
|
|||
|
|
@ -245,6 +245,10 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv)
|
|||
drm_gem_lru_init(&priv->lru.willneed, &priv->lru.lock);
|
||||
drm_gem_lru_init(&priv->lru.dontneed, &priv->lru.lock);
|
||||
|
||||
/* Initialize stall-on-fault */
|
||||
spin_lock_init(&priv->fault_stall_lock);
|
||||
priv->stall_enabled = true;
|
||||
|
||||
/* Teach lockdep about lock ordering wrt. shrinker: */
|
||||
fs_reclaim_acquire(GFP_KERNEL);
|
||||
might_lock(&priv->lru.lock);
|
||||
|
|
@ -926,7 +930,7 @@ static const struct drm_driver msm_driver = {
|
|||
* is no external component that we need to add since LVDS is within MDP4
|
||||
* itself.
|
||||
*/
|
||||
static int add_components_mdp(struct device *master_dev,
|
||||
static int add_mdp_components(struct device *master_dev,
|
||||
struct component_match **matchptr)
|
||||
{
|
||||
struct device_node *np = master_dev->of_node;
|
||||
|
|
@ -1030,7 +1034,7 @@ static int add_gpu_components(struct device *dev,
|
|||
if (!np)
|
||||
return 0;
|
||||
|
||||
if (of_device_is_available(np))
|
||||
if (of_device_is_available(np) && adreno_has_gpu(np))
|
||||
drm_of_component_match_add(dev, matchptr, component_compare_of, np);
|
||||
|
||||
of_node_put(np);
|
||||
|
|
@ -1071,7 +1075,7 @@ int msm_drv_probe(struct device *master_dev,
|
|||
|
||||
/* Add mdp components if we have KMS. */
|
||||
if (kms_init) {
|
||||
ret = add_components_mdp(master_dev, &match);
|
||||
ret = add_mdp_components(master_dev, &match);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -222,6 +222,29 @@ struct msm_drm_private {
|
|||
* the sw hangcheck mechanism.
|
||||
*/
|
||||
bool disable_err_irq;
|
||||
|
||||
/**
|
||||
* @fault_stall_lock:
|
||||
*
|
||||
* Serialize changes to stall-on-fault state.
|
||||
*/
|
||||
spinlock_t fault_stall_lock;
|
||||
|
||||
/**
|
||||
* @fault_stall_reenable_time:
|
||||
*
|
||||
* If stall_enabled is false, when to reenable stall-on-fault.
|
||||
* Protected by @fault_stall_lock.
|
||||
*/
|
||||
ktime_t stall_reenable_time;
|
||||
|
||||
/**
|
||||
* @stall_enabled:
|
||||
*
|
||||
* Whether stall-on-fault is currently enabled. Protected by
|
||||
* @fault_stall_lock.
|
||||
*/
|
||||
bool stall_enabled;
|
||||
};
|
||||
|
||||
const struct msm_format *mdp_get_format(struct msm_kms *kms, uint32_t format, uint64_t modifier);
|
||||
|
|
|
|||
|
|
@ -85,6 +85,15 @@ void __msm_gem_submit_destroy(struct kref *kref)
|
|||
container_of(kref, struct msm_gem_submit, ref);
|
||||
unsigned i;
|
||||
|
||||
/*
|
||||
* In error paths, we could unref the submit without calling
|
||||
* drm_sched_entity_push_job(), so msm_job_free() will never
|
||||
* get called. Since drm_sched_job_cleanup() will NULL out
|
||||
* s_fence, we can use that to detect this case.
|
||||
*/
|
||||
if (submit->base.s_fence)
|
||||
drm_sched_job_cleanup(&submit->base);
|
||||
|
||||
if (submit->fence_id) {
|
||||
spin_lock(&submit->queue->idr_lock);
|
||||
idr_remove(&submit->queue->fence_idr, submit->fence_id);
|
||||
|
|
@ -649,6 +658,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
|
|||
struct msm_ringbuffer *ring;
|
||||
struct msm_submit_post_dep *post_deps = NULL;
|
||||
struct drm_syncobj **syncobjs_to_reset = NULL;
|
||||
struct sync_file *sync_file = NULL;
|
||||
int out_fence_fd = -1;
|
||||
unsigned i;
|
||||
int ret;
|
||||
|
|
@ -858,7 +868,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
|
|||
}
|
||||
|
||||
if (ret == 0 && args->flags & MSM_SUBMIT_FENCE_FD_OUT) {
|
||||
struct sync_file *sync_file = sync_file_create(submit->user_fence);
|
||||
sync_file = sync_file_create(submit->user_fence);
|
||||
if (!sync_file) {
|
||||
ret = -ENOMEM;
|
||||
} else {
|
||||
|
|
@ -892,8 +902,11 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
|
|||
out_unlock:
|
||||
mutex_unlock(&queue->lock);
|
||||
out_post_unlock:
|
||||
if (ret && (out_fence_fd >= 0))
|
||||
if (ret && (out_fence_fd >= 0)) {
|
||||
put_unused_fd(out_fence_fd);
|
||||
if (sync_file)
|
||||
fput(sync_file->file);
|
||||
}
|
||||
|
||||
if (!IS_ERR_OR_NULL(submit)) {
|
||||
msm_gem_submit_put(submit);
|
||||
|
|
|
|||
|
|
@ -257,7 +257,8 @@ static void msm_gpu_crashstate_get_bo(struct msm_gpu_state *state,
|
|||
}
|
||||
|
||||
static void msm_gpu_crashstate_capture(struct msm_gpu *gpu,
|
||||
struct msm_gem_submit *submit, char *comm, char *cmd)
|
||||
struct msm_gem_submit *submit, struct msm_gpu_fault_info *fault_info,
|
||||
char *comm, char *cmd)
|
||||
{
|
||||
struct msm_gpu_state *state;
|
||||
|
||||
|
|
@ -276,7 +277,8 @@ static void msm_gpu_crashstate_capture(struct msm_gpu *gpu,
|
|||
/* Fill in the additional crash state information */
|
||||
state->comm = kstrdup(comm, GFP_KERNEL);
|
||||
state->cmd = kstrdup(cmd, GFP_KERNEL);
|
||||
state->fault_info = gpu->fault_info;
|
||||
if (fault_info)
|
||||
state->fault_info = *fault_info;
|
||||
|
||||
if (submit) {
|
||||
int i;
|
||||
|
|
@ -308,7 +310,8 @@ static void msm_gpu_crashstate_capture(struct msm_gpu *gpu,
|
|||
}
|
||||
#else
|
||||
static void msm_gpu_crashstate_capture(struct msm_gpu *gpu,
|
||||
struct msm_gem_submit *submit, char *comm, char *cmd)
|
||||
struct msm_gem_submit *submit, struct msm_gpu_fault_info *fault_info,
|
||||
char *comm, char *cmd)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
|
@ -405,7 +408,7 @@ static void recover_worker(struct kthread_work *work)
|
|||
|
||||
/* Record the crash state */
|
||||
pm_runtime_get_sync(&gpu->pdev->dev);
|
||||
msm_gpu_crashstate_capture(gpu, submit, comm, cmd);
|
||||
msm_gpu_crashstate_capture(gpu, submit, NULL, comm, cmd);
|
||||
|
||||
kfree(cmd);
|
||||
kfree(comm);
|
||||
|
|
@ -459,9 +462,8 @@ static void recover_worker(struct kthread_work *work)
|
|||
msm_gpu_retire(gpu);
|
||||
}
|
||||
|
||||
static void fault_worker(struct kthread_work *work)
|
||||
void msm_gpu_fault_crashstate_capture(struct msm_gpu *gpu, struct msm_gpu_fault_info *fault_info)
|
||||
{
|
||||
struct msm_gpu *gpu = container_of(work, struct msm_gpu, fault_work);
|
||||
struct msm_gem_submit *submit;
|
||||
struct msm_ringbuffer *cur_ring = gpu->funcs->active_ring(gpu);
|
||||
char *comm = NULL, *cmd = NULL;
|
||||
|
|
@ -484,16 +486,13 @@ static void fault_worker(struct kthread_work *work)
|
|||
|
||||
/* Record the crash state */
|
||||
pm_runtime_get_sync(&gpu->pdev->dev);
|
||||
msm_gpu_crashstate_capture(gpu, submit, comm, cmd);
|
||||
msm_gpu_crashstate_capture(gpu, submit, fault_info, comm, cmd);
|
||||
pm_runtime_put_sync(&gpu->pdev->dev);
|
||||
|
||||
kfree(cmd);
|
||||
kfree(comm);
|
||||
|
||||
resume_smmu:
|
||||
memset(&gpu->fault_info, 0, sizeof(gpu->fault_info));
|
||||
gpu->aspace->mmu->funcs->resume_translation(gpu->aspace->mmu);
|
||||
|
||||
mutex_unlock(&gpu->lock);
|
||||
}
|
||||
|
||||
|
|
@ -882,7 +881,6 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
|
|||
init_waitqueue_head(&gpu->retire_event);
|
||||
kthread_init_work(&gpu->retire_work, retire_worker);
|
||||
kthread_init_work(&gpu->recover_work, recover_worker);
|
||||
kthread_init_work(&gpu->fault_work, fault_worker);
|
||||
|
||||
priv->hangcheck_period = DRM_MSM_HANGCHECK_DEFAULT_PERIOD;
|
||||
|
||||
|
|
|
|||
|
|
@ -253,12 +253,6 @@ struct msm_gpu {
|
|||
#define DRM_MSM_HANGCHECK_PROGRESS_RETRIES 3
|
||||
struct timer_list hangcheck_timer;
|
||||
|
||||
/* Fault info for most recent iova fault: */
|
||||
struct msm_gpu_fault_info fault_info;
|
||||
|
||||
/* work for handling GPU ioval faults: */
|
||||
struct kthread_work fault_work;
|
||||
|
||||
/* work for handling GPU recovery: */
|
||||
struct kthread_work recover_work;
|
||||
|
||||
|
|
@ -668,6 +662,7 @@ msm_gpu_create_private_address_space(struct msm_gpu *gpu, struct task_struct *ta
|
|||
void msm_gpu_cleanup(struct msm_gpu *gpu);
|
||||
|
||||
struct msm_gpu *adreno_load_gpu(struct drm_device *dev);
|
||||
bool adreno_has_gpu(struct device_node *node);
|
||||
void __init adreno_register(void);
|
||||
void __exit adreno_unregister(void);
|
||||
|
||||
|
|
@ -705,6 +700,8 @@ static inline void msm_gpu_crashstate_put(struct msm_gpu *gpu)
|
|||
mutex_unlock(&gpu->lock);
|
||||
}
|
||||
|
||||
void msm_gpu_fault_crashstate_capture(struct msm_gpu *gpu, struct msm_gpu_fault_info *fault_info);
|
||||
|
||||
/*
|
||||
* Simple macro to semi-cleanly add the MAP_PRIV flag for targets that can
|
||||
* support expanded privileges
|
||||
|
|
|
|||
|
|
@ -345,7 +345,6 @@ static int msm_gpu_fault_handler(struct iommu_domain *domain, struct device *dev
|
|||
unsigned long iova, int flags, void *arg)
|
||||
{
|
||||
struct msm_iommu *iommu = arg;
|
||||
struct msm_mmu *mmu = &iommu->base;
|
||||
struct adreno_smmu_priv *adreno_smmu = dev_get_drvdata(iommu->base.dev);
|
||||
struct adreno_smmu_fault_info info, *ptr = NULL;
|
||||
|
||||
|
|
@ -359,9 +358,6 @@ static int msm_gpu_fault_handler(struct iommu_domain *domain, struct device *dev
|
|||
|
||||
pr_warn_ratelimited("*** fault: iova=%16lx, flags=%d\n", iova, flags);
|
||||
|
||||
if (mmu->funcs->resume_translation)
|
||||
mmu->funcs->resume_translation(mmu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -376,12 +372,12 @@ static int msm_disp_fault_handler(struct iommu_domain *domain, struct device *de
|
|||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static void msm_iommu_resume_translation(struct msm_mmu *mmu)
|
||||
static void msm_iommu_set_stall(struct msm_mmu *mmu, bool enable)
|
||||
{
|
||||
struct adreno_smmu_priv *adreno_smmu = dev_get_drvdata(mmu->dev);
|
||||
|
||||
if (adreno_smmu->resume_translation)
|
||||
adreno_smmu->resume_translation(adreno_smmu->cookie, true);
|
||||
if (adreno_smmu->set_stall)
|
||||
adreno_smmu->set_stall(adreno_smmu->cookie, enable);
|
||||
}
|
||||
|
||||
static void msm_iommu_detach(struct msm_mmu *mmu)
|
||||
|
|
@ -431,7 +427,7 @@ static const struct msm_mmu_funcs funcs = {
|
|||
.map = msm_iommu_map,
|
||||
.unmap = msm_iommu_unmap,
|
||||
.destroy = msm_iommu_destroy,
|
||||
.resume_translation = msm_iommu_resume_translation,
|
||||
.set_stall = msm_iommu_set_stall,
|
||||
};
|
||||
|
||||
struct msm_mmu *msm_iommu_new(struct device *dev, unsigned long quirks)
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ struct msm_mmu_funcs {
|
|||
size_t len, int prot);
|
||||
int (*unmap)(struct msm_mmu *mmu, uint64_t iova, size_t len);
|
||||
void (*destroy)(struct msm_mmu *mmu);
|
||||
void (*resume_translation)(struct msm_mmu *mmu);
|
||||
void (*set_stall)(struct msm_mmu *mmu, bool enable);
|
||||
};
|
||||
|
||||
enum msm_mmu_type {
|
||||
|
|
|
|||
|
|
@ -2255,7 +2255,8 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords)
|
|||
<reg32 offset="0" name="0">
|
||||
<bitfield name="CLEAR_ON_CHIP_TS" pos="0" type="boolean"/>
|
||||
<bitfield name="CLEAR_RESOURCE_TABLE" pos="1" type="boolean"/>
|
||||
<bitfield name="CLEAR_GLOBAL_LOCAL_TS" pos="2" type="boolean"/>
|
||||
<bitfield name="CLEAR_BV_BR_COUNTER" pos="2" type="boolean"/>
|
||||
<bitfield name="RESET_GLOBAL_LOCAL_TS" pos="3" type="boolean"/>
|
||||
</reg32>
|
||||
</domain>
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import collections
|
|||
import argparse
|
||||
import time
|
||||
import datetime
|
||||
import re
|
||||
|
||||
class Error(Exception):
|
||||
def __init__(self, message):
|
||||
|
|
@ -877,13 +878,14 @@ The rules-ng-ng source files this header was generated from are:
|
|||
""")
|
||||
maxlen = 0
|
||||
for filepath in p.xml_files:
|
||||
maxlen = max(maxlen, len(filepath))
|
||||
new_filepath = re.sub("^.+drivers","drivers",filepath)
|
||||
maxlen = max(maxlen, len(new_filepath))
|
||||
for filepath in p.xml_files:
|
||||
pad = " " * (maxlen - len(filepath))
|
||||
pad = " " * (maxlen - len(new_filepath))
|
||||
filesize = str(os.path.getsize(filepath))
|
||||
filesize = " " * (7 - len(filesize)) + filesize
|
||||
filetime = time.ctime(os.path.getmtime(filepath))
|
||||
print("- " + filepath + pad + " (" + filesize + " bytes, from " + filetime + ")")
|
||||
print("- " + new_filepath + pad + " (" + filesize + " bytes, from <stripped>)")
|
||||
if p.copyright_year:
|
||||
current_year = str(datetime.date.today().year)
|
||||
print()
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@
|
|||
#include "nouveau_acpi.h"
|
||||
|
||||
static struct ida bl_ida;
|
||||
#define BL_NAME_SIZE 15 // 12 for name + 2 for digits + 1 for '\0'
|
||||
#define BL_NAME_SIZE 24 // 12 for name + 11 for digits + 1 for '\0'
|
||||
|
||||
static bool
|
||||
nouveau_get_backlight_name(char backlight_name[BL_NAME_SIZE],
|
||||
|
|
|
|||
|
|
@ -637,12 +637,18 @@ r535_gsp_rpc_push(struct nvkm_gsp *gsp, void *payload,
|
|||
if (payload_size > max_payload_size) {
|
||||
const u32 fn = rpc->function;
|
||||
u32 remain_payload_size = payload_size;
|
||||
void *next;
|
||||
|
||||
/* Adjust length, and send initial RPC. */
|
||||
rpc->length = sizeof(*rpc) + max_payload_size;
|
||||
msg->checksum = rpc->length;
|
||||
/* Send initial RPC. */
|
||||
next = r535_gsp_rpc_get(gsp, fn, max_payload_size);
|
||||
if (IS_ERR(next)) {
|
||||
repv = next;
|
||||
goto done;
|
||||
}
|
||||
|
||||
repv = r535_gsp_rpc_send(gsp, payload, NVKM_GSP_RPC_REPLY_NOWAIT, 0);
|
||||
memcpy(next, payload, max_payload_size);
|
||||
|
||||
repv = r535_gsp_rpc_send(gsp, next, NVKM_GSP_RPC_REPLY_NOWAIT, 0);
|
||||
if (IS_ERR(repv))
|
||||
goto done;
|
||||
|
||||
|
|
@ -653,7 +659,6 @@ r535_gsp_rpc_push(struct nvkm_gsp *gsp, void *payload,
|
|||
while (remain_payload_size) {
|
||||
u32 size = min(remain_payload_size,
|
||||
max_payload_size);
|
||||
void *next;
|
||||
|
||||
next = r535_gsp_rpc_get(gsp, NV_VGPU_MSG_FUNCTION_CONTINUATION_RECORD, size);
|
||||
if (IS_ERR(next)) {
|
||||
|
|
@ -674,6 +679,8 @@ r535_gsp_rpc_push(struct nvkm_gsp *gsp, void *payload,
|
|||
/* Wait for reply. */
|
||||
repv = r535_gsp_rpc_handle_reply(gsp, fn, policy, payload_size +
|
||||
sizeof(*rpc));
|
||||
if (!IS_ERR(repv))
|
||||
kvfree(msg);
|
||||
} else {
|
||||
repv = r535_gsp_rpc_send(gsp, payload, policy, gsp_rpc_len);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ r535_mmu_vaspace_new(struct nvkm_vmm *vmm, u32 handle, bool external)
|
|||
page_shift -= desc->bits;
|
||||
|
||||
ctrl->levels[i].physAddress = pd->pt[0]->addr;
|
||||
ctrl->levels[i].size = (1 << desc->bits) * desc->size;
|
||||
ctrl->levels[i].size = BIT_ULL(desc->bits) * desc->size;
|
||||
ctrl->levels[i].aperture = 1;
|
||||
ctrl->levels[i].pageShift = page_shift;
|
||||
|
||||
|
|
|
|||
|
|
@ -974,7 +974,7 @@ static void ssd130x_clear_screen(struct ssd130x_device *ssd130x, u8 *data_array)
|
|||
|
||||
static void ssd132x_clear_screen(struct ssd130x_device *ssd130x, u8 *data_array)
|
||||
{
|
||||
unsigned int columns = DIV_ROUND_UP(ssd130x->height, SSD132X_SEGMENT_WIDTH);
|
||||
unsigned int columns = DIV_ROUND_UP(ssd130x->width, SSD132X_SEGMENT_WIDTH);
|
||||
unsigned int height = ssd130x->height;
|
||||
|
||||
memset(data_array, 0, columns * height);
|
||||
|
|
|
|||
|
|
@ -199,7 +199,6 @@ v3d_job_update_stats(struct v3d_job *job, enum v3d_queue queue)
|
|||
struct v3d_dev *v3d = job->v3d;
|
||||
struct v3d_file_priv *file = job->file->driver_priv;
|
||||
struct v3d_stats *global_stats = &v3d->queue[queue].stats;
|
||||
struct v3d_stats *local_stats = &file->stats[queue];
|
||||
u64 now = local_clock();
|
||||
unsigned long flags;
|
||||
|
||||
|
|
@ -209,7 +208,12 @@ v3d_job_update_stats(struct v3d_job *job, enum v3d_queue queue)
|
|||
else
|
||||
preempt_disable();
|
||||
|
||||
v3d_stats_update(local_stats, now);
|
||||
/* Don't update the local stats if the file context has already closed */
|
||||
if (file)
|
||||
v3d_stats_update(&file->stats[queue], now);
|
||||
else
|
||||
drm_dbg(&v3d->drm, "The file descriptor was closed before job completion\n");
|
||||
|
||||
v3d_stats_update(global_stats, now);
|
||||
|
||||
if (IS_ENABLED(CONFIG_LOCKDEP))
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ static void xe_gt_enable_host_l2_vram(struct xe_gt *gt)
|
|||
xe_gt_mcr_multicast_write(gt, XE2_GAMREQSTRM_CTRL, reg);
|
||||
}
|
||||
|
||||
xe_gt_mcr_multicast_write(gt, XEHPC_L3CLOS_MASK(3), 0x3);
|
||||
xe_gt_mcr_multicast_write(gt, XEHPC_L3CLOS_MASK(3), 0xF);
|
||||
xe_force_wake_put(gt_to_fw(gt), fw_ref);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -137,6 +137,14 @@ void xe_gt_tlb_invalidation_reset(struct xe_gt *gt)
|
|||
struct xe_gt_tlb_invalidation_fence *fence, *next;
|
||||
int pending_seqno;
|
||||
|
||||
/*
|
||||
* we can get here before the CTs are even initialized if we're wedging
|
||||
* very early, in which case there are not going to be any pending
|
||||
* fences so we can bail immediately.
|
||||
*/
|
||||
if (!xe_guc_ct_initialized(>->uc.guc.ct))
|
||||
return;
|
||||
|
||||
/*
|
||||
* CT channel is already disabled at this point. No new TLB requests can
|
||||
* appear.
|
||||
|
|
|
|||
|
|
@ -514,6 +514,9 @@ void xe_guc_ct_disable(struct xe_guc_ct *ct)
|
|||
*/
|
||||
void xe_guc_ct_stop(struct xe_guc_ct *ct)
|
||||
{
|
||||
if (!xe_guc_ct_initialized(ct))
|
||||
return;
|
||||
|
||||
xe_guc_ct_set_state(ct, XE_GUC_CT_STATE_STOPPED);
|
||||
stop_g2h_handler(ct);
|
||||
}
|
||||
|
|
@ -760,7 +763,7 @@ static int __guc_ct_send_locked(struct xe_guc_ct *ct, const u32 *action,
|
|||
u16 seqno;
|
||||
int ret;
|
||||
|
||||
xe_gt_assert(gt, ct->state != XE_GUC_CT_STATE_NOT_INITIALIZED);
|
||||
xe_gt_assert(gt, xe_guc_ct_initialized(ct));
|
||||
xe_gt_assert(gt, !g2h_len || !g2h_fence);
|
||||
xe_gt_assert(gt, !num_g2h || !g2h_fence);
|
||||
xe_gt_assert(gt, !g2h_len || num_g2h);
|
||||
|
|
@ -1344,7 +1347,7 @@ static int g2h_read(struct xe_guc_ct *ct, u32 *msg, bool fast_path)
|
|||
u32 action;
|
||||
u32 *hxg;
|
||||
|
||||
xe_gt_assert(gt, ct->state != XE_GUC_CT_STATE_NOT_INITIALIZED);
|
||||
xe_gt_assert(gt, xe_guc_ct_initialized(ct));
|
||||
lockdep_assert_held(&ct->fast_lock);
|
||||
|
||||
if (ct->state == XE_GUC_CT_STATE_DISABLED)
|
||||
|
|
|
|||
|
|
@ -22,6 +22,11 @@ void xe_guc_ct_snapshot_print(struct xe_guc_ct_snapshot *snapshot, struct drm_pr
|
|||
void xe_guc_ct_snapshot_free(struct xe_guc_ct_snapshot *snapshot);
|
||||
void xe_guc_ct_print(struct xe_guc_ct *ct, struct drm_printer *p, bool want_ctb);
|
||||
|
||||
static inline bool xe_guc_ct_initialized(struct xe_guc_ct *ct)
|
||||
{
|
||||
return ct->state != XE_GUC_CT_STATE_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
static inline bool xe_guc_ct_enabled(struct xe_guc_ct *ct)
|
||||
{
|
||||
return ct->state == XE_GUC_CT_STATE_ENABLED;
|
||||
|
|
|
|||
|
|
@ -1068,7 +1068,7 @@ int xe_guc_pc_start(struct xe_guc_pc *pc)
|
|||
goto out;
|
||||
}
|
||||
|
||||
memset(pc->bo->vmap.vaddr, 0, size);
|
||||
xe_map_memset(xe, &pc->bo->vmap, 0, 0, size);
|
||||
slpc_shared_data_write(pc, header.size, size);
|
||||
|
||||
earlier = ktime_get();
|
||||
|
|
|
|||
|
|
@ -1762,6 +1762,9 @@ int xe_guc_submit_reset_prepare(struct xe_guc *guc)
|
|||
{
|
||||
int ret;
|
||||
|
||||
if (!guc->submission_state.initialized)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Using an atomic here rather than submission_state.lock as this
|
||||
* function can be called while holding the CT lock (engine reset
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user