summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/amdgpu
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-04-24 11:33:23 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-04-24 11:33:23 -0700
commit92c4c9fdc838d3b41a996bb700ea64b9e78fc7ea (patch)
treee5a1763ce1295ccdeb94f4e26ee52eb4f3c3aed6 /drivers/gpu/drm/amd/amdgpu
parent892c894b4ba4e4eb835f99de6fe7c41871e6d4f8 (diff)
parente49712ef03dbc4e282dd0e76469642279c2811e5 (diff)
Merge tag 'drm-next-2026-04-24' of https://gitlab.freedesktop.org/drm/kernel
Pull drm next fixes from Dave Airlie: "This is the first of two fixes for the merge PRs, the other is based on 7.0 branch. This mostly AMD fixes, a couple of weeks of backlog built up and this weeks. The main complaint I've seen is some boot warnings around the FP code handling which this should fix. Otherwise a single rcar-du and a single i915 fix. amdgpu: - SMU 14 fixes - Partition fixes - SMUIO 15.x fix - SR-IOV fixes - JPEG fix - PSP 15.x fix - NBIF fix - Devcoredump fixes - DPC fix - RAS fixes - Aldebaran smu fix - IP discovery fix - SDMA 7.1 fix - Runtime pm fix - MES 12.1 fix - DML2 fixes - DCN 4.2 fixes - YCbCr fixes - Freesync fixes - ISM fixes - Overlay cursor fix - DC FP fixes - UserQ locking fixes - DC idle state manager fix - ASPM fix - GPUVM SVM fix - DCE 6 fix amdkfd: - Fix memory clear handling - num_of_nodes bounds check fix i915: - Fix uninitialized variable in the alignment loop [psr] rcar-du: - fix NULL-ptr crash" * tag 'drm-next-2026-04-24' of https://gitlab.freedesktop.org/drm/kernel: (75 commits) drm/amdkfd: Add upper bound check for num_of_nodes drm: rcar-du: Fix crash when no CMM is available drm/amd/display: Disable 10-bit truncation and dithering on DCE 6.x drm/amdgpu: OR init_pte_flags into invalid leaf PTE updates drm/amd: Adjust ASPM support quirk to cover more Intel hosts drm/amd/display: Undo accidental fix revert in amdgpu_dm_ism.c drm/i915/psr: Init variable to avoid early exit from et alignment loop drm/amdgpu: drop userq fence driver refs out of fence process() drm/amdgpu/userq: unpin and unref doorbell and wptr outside mutex drm/amdgpu/userq: use pm_runtime_resume_and_get and fix err handling drm/amdgpu/userq: unmap_helper dont return the queue state drm/amdgpu/userq: unmap is to be called before freeing doorbell/wptr bo drm/amdgpu/userq: hold root bo lock in caller of input_va_validate drm/amdgpu/userq: caller to take reserv lock for vas_list_cleanup drm/amdgpu/userq: create_mqd does not need userq_mutex drm/amdgpu/userq: dont lock root bo with userq_mutex held drm/amdgpu/userq: fix kerneldoc for amdgpu_userq_ensure_ev_fence drm/amdgpu/userq: clean the VA mapping list for failed queue creation drm/amdgpu/userq: avoid uneccessary locking in amdgpu_userq_create drm/amd/display: Fix ISM teardown crash from NULL dc dereference ...
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c36
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c9
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_device.c20
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c140
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c47
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm_cpu.c12
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c7
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c31
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c52
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mes_userqueue.c21
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mes_v12_1.c8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/nbif_v6_3_1.c9
-rw-r--r--drivers/gpu/drm/amd/amdgpu/psp_v15_0.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v7_1.c12
19 files changed, 301 insertions, 121 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
index 29b400cdd6d5..72a5a29e63f6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
@@ -1735,7 +1735,8 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
alloc_domain = AMDGPU_GEM_DOMAIN_GTT;
alloc_flags = 0;
} else {
- alloc_flags = AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE;
+ alloc_flags = AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE |
+ AMDGPU_GEM_CREATE_VRAM_CLEARED;
alloc_flags |= (flags & KFD_IOC_ALLOC_MEM_FLAGS_PUBLIC) ?
AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED : 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
index b04fa9fd90b7..92c98e999efe 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
@@ -866,6 +866,7 @@ amdgpu_connector_vga_detect(struct drm_connector *connector, bool force)
if (dret) {
amdgpu_connector->detected_by_load = false;
drm_edid_free(amdgpu_connector->edid);
+ amdgpu_connector->edid = NULL;
amdgpu_connector_get_edid(connector);
if (!amdgpu_connector->edid) {
@@ -882,6 +883,7 @@ amdgpu_connector_vga_detect(struct drm_connector *connector, bool force)
*/
if (amdgpu_connector->use_digital && amdgpu_connector->shared_ddc) {
drm_edid_free(amdgpu_connector->edid);
+ amdgpu_connector->edid = NULL;
ret = connector_status_disconnected;
} else {
ret = connector_status_connected;
@@ -977,6 +979,7 @@ static void amdgpu_connector_shared_ddc(enum drm_connector_status *status,
if (!amdgpu_display_hpd_sense(adev,
amdgpu_connector->hpd.hpd)) {
drm_edid_free(amdgpu_connector->edid);
+ amdgpu_connector->edid = NULL;
*status = connector_status_disconnected;
}
}
@@ -1046,6 +1049,7 @@ amdgpu_connector_dvi_detect(struct drm_connector *connector, bool force)
if (dret) {
amdgpu_connector->detected_by_load = false;
drm_edid_free(amdgpu_connector->edid);
+ amdgpu_connector->edid = NULL;
amdgpu_connector_get_edid(connector);
if (!amdgpu_connector->edid) {
@@ -1062,6 +1066,7 @@ amdgpu_connector_dvi_detect(struct drm_connector *connector, bool force)
*/
if ((!amdgpu_connector->use_digital) && amdgpu_connector->shared_ddc) {
drm_edid_free(amdgpu_connector->edid);
+ amdgpu_connector->edid = NULL;
ret = connector_status_disconnected;
} else {
ret = connector_status_connected;
@@ -1412,6 +1417,7 @@ amdgpu_connector_dp_detect(struct drm_connector *connector, bool force)
}
drm_edid_free(amdgpu_connector->edid);
+ amdgpu_connector->edid = NULL;
if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
(connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c
index c72c345334d0..4e6e390854e6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c
@@ -32,6 +32,8 @@ static const guid_t BOOT = BOOT_TYPE;
static const guid_t CRASHDUMP = AMD_CRASHDUMP;
static const guid_t RUNTIME = AMD_GPU_NONSTANDARD_ERROR;
+#define CPER_SIGNATURE_SZ (sizeof(((struct cper_hdr *)0)->signature))
+
static void __inc_entry_length(struct cper_hdr *hdr, uint32_t size)
{
hdr->record_length += size;
@@ -425,23 +427,40 @@ int amdgpu_cper_generate_ce_records(struct amdgpu_device *adev,
static bool amdgpu_cper_is_hdr(struct amdgpu_ring *ring, u64 pos)
{
- struct cper_hdr *chdr;
+ char signature[CPER_SIGNATURE_SZ];
+
+ if ((pos << 2) >= ring->ring_size)
+ return false;
- chdr = (struct cper_hdr *)&(ring->ring[pos]);
- return strcmp(chdr->signature, "CPER") ? false : true;
+ if ((pos << 2) + CPER_SIGNATURE_SZ <= ring->ring_size) {
+ memcpy(signature, &ring->ring[pos], CPER_SIGNATURE_SZ);
+ } else {
+ u32 chunk = ring->ring_size - (pos << 2);
+
+ memcpy(signature, &ring->ring[pos], chunk);
+ memcpy(signature + chunk, ring->ring, CPER_SIGNATURE_SZ - chunk);
+ }
+
+ return !memcmp(signature, "CPER", CPER_SIGNATURE_SZ);
}
static u32 amdgpu_cper_ring_get_ent_sz(struct amdgpu_ring *ring, u64 pos)
{
- struct cper_hdr *chdr;
+ struct cper_hdr chdr;
u64 p;
u32 chunk, rec_len = 0;
- chdr = (struct cper_hdr *)&(ring->ring[pos]);
chunk = ring->ring_size - (pos << 2);
- if (!strcmp(chdr->signature, "CPER")) {
- rec_len = chdr->record_length;
+ if (amdgpu_cper_is_hdr(ring, pos)) {
+ if (chunk >= sizeof(chdr)) {
+ memcpy(&chdr, &ring->ring[pos], sizeof(chdr));
+ } else {
+ memcpy(&chdr, &ring->ring[pos], chunk);
+ memcpy((u8 *)&chdr + chunk, ring->ring, sizeof(chdr) - chunk);
+ }
+
+ rec_len = chdr.record_length;
goto calc;
}
@@ -450,8 +469,7 @@ static u32 amdgpu_cper_ring_get_ent_sz(struct amdgpu_ring *ring, u64 pos)
goto calc;
for (p = pos + 1; p <= ring->buf_mask; p++) {
- chdr = (struct cper_hdr *)&(ring->ring[p]);
- if (!strcmp(chdr->signature, "CPER")) {
+ if (amdgpu_cper_is_hdr(ring, p)) {
rec_len = (p - pos) << 2;
goto calc;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c
index 3f1cc2265645..d386bc775d03 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c
@@ -464,6 +464,9 @@ static void amdgpu_devcoredump_deferred_work(struct work_struct *work)
struct amdgpu_device *adev = container_of(work, typeof(*adev), coredump_work);
struct amdgpu_coredump_info *coredump = adev->coredump;
+ if (!coredump)
+ goto end;
+
/* Do a one-time preparation of the coredump output because
* repeatingly calling drm_coredump_printer is very slow.
*/
@@ -499,7 +502,7 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check,
int i, off, idx;
/* No need to generate a new coredump if there's one in progress already. */
- if (work_pending(&adev->coredump_work))
+ if (work_busy(&adev->coredump_work))
return;
if (job && job->pasid)
@@ -511,7 +514,6 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check,
coredump->skip_vram_check = skip_vram_check;
coredump->reset_vram_lost = vram_lost;
- coredump->pasid = job->pasid;
if (job && job->pasid) {
struct amdgpu_task_info *ti;
@@ -521,6 +523,7 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check,
coredump->reset_task_info = *ti;
amdgpu_vm_put_task_info(ti);
}
+ coredump->pasid = job->pasid;
coredump->num_ibs = job->num_ibs;
for (i = 0; i < job->num_ibs; ++i) {
coredump->ibs[i].gpu_addr = job->ibs[i].gpu_addr;
@@ -563,7 +566,7 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check,
coredump->rings[idx].offset = off;
memcpy(&coredump->rings_dw[off], ring->ring, ring->ring_size);
- off += ring->ring_size;
+ off += ring->ring_size / 4;
idx++;
}
coredump->num_rings = idx;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 584c9ec28bf1..737ef1ef96a5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -1334,18 +1334,15 @@ static bool amdgpu_device_aspm_support_quirk(struct amdgpu_device *adev)
#if IS_ENABLED(CONFIG_X86)
struct cpuinfo_x86 *c = &cpu_data(0);
- if (!(amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(12, 0, 0) ||
- amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(12, 0, 1)))
- return false;
-
- if (c->x86 == 6 &&
- adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN5) {
+ if (c->x86_vendor == X86_VENDOR_INTEL) {
switch (c->x86_model) {
case VFM_MODEL(INTEL_ALDERLAKE):
case VFM_MODEL(INTEL_ALDERLAKE_L):
case VFM_MODEL(INTEL_RAPTORLAKE):
case VFM_MODEL(INTEL_RAPTORLAKE_P):
case VFM_MODEL(INTEL_RAPTORLAKE_S):
+ case VFM_MODEL(INTEL_TIGERLAKE):
+ case VFM_MODEL(INTEL_TIGERLAKE_L):
return true;
default:
return false;
@@ -5518,8 +5515,6 @@ static void amdgpu_device_recovery_prepare(struct amdgpu_device *adev,
list_add_tail(&tmp_adev->reset_list, device_list);
if (adev->shutdown)
tmp_adev->shutdown = true;
- if (amdgpu_reset_in_dpc(adev))
- tmp_adev->pcie_reset_ctx.in_link_reset = true;
}
if (!list_is_first(&adev->reset_list, device_list))
list_rotate_to_front(&adev->reset_list, device_list);
@@ -6291,6 +6286,9 @@ pci_ers_result_t amdgpu_pci_error_detected(struct pci_dev *pdev, pci_channel_sta
amdgpu_reset_set_dpc_status(adev, true);
mutex_lock(&hive->hive_lock);
+ } else {
+ if (amdgpu_device_bus_status_check(adev))
+ amdgpu_reset_set_dpc_status(adev, true);
}
memset(&reset_context, 0, sizeof(reset_context));
INIT_LIST_HEAD(&device_list);
@@ -6411,6 +6409,7 @@ pci_ers_result_t amdgpu_pci_slot_reset(struct pci_dev *pdev)
list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head)
tmp_adev->pcie_reset_ctx.in_link_reset = true;
} else {
+ adev->pcie_reset_ctx.in_link_reset = true;
set_bit(AMDGPU_SKIP_HW_RESET, &reset_context.flags);
}
@@ -6467,9 +6466,10 @@ void amdgpu_pci_resume(struct pci_dev *pdev)
tmp_adev->pcie_reset_ctx.in_link_reset = false;
list_add_tail(&tmp_adev->reset_list, &device_list);
}
- } else
+ } else {
+ adev->pcie_reset_ctx.in_link_reset = false;
list_add_tail(&adev->reset_list, &device_list);
-
+ }
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);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
index 8ec5465c3349..fcad7daaa41b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
@@ -535,10 +535,11 @@ static int amdgpu_discovery_get_table_info(struct amdgpu_device *adev,
*info = &bhdrv2->table_list[table_id];
break;
case 1:
+ case 0:
*info = &bhdr->table_list[table_id];
break;
default:
- dev_err(adev->dev, "Invalid ip discovery table version\n");
+ dev_err(adev->dev, "Invalid ip discovery table version %d\n",bhdr->version_major);
return -EINVAL;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
index 2956e45c9254..b8ca876694ff 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
@@ -2013,6 +2013,8 @@ static void amdgpu_gfx_sysfs_xcp_fini(struct amdgpu_device *adev)
(xcp_mgr->funcs && xcp_mgr->funcs->switch_partition_mode);
device_remove_file(adev->dev, &dev_attr_current_compute_partition);
+ device_remove_file(adev->dev, &dev_attr_compute_partition_mem_alloc_mode);
+
if (xcp_switch_supported)
device_remove_file(adev->dev,
&dev_attr_available_compute_partition);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
index bfca5b040a32..d5abf785ca17 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
@@ -239,13 +239,12 @@ int amdgpu_userq_input_va_validate(struct amdgpu_device *adev,
u64 size;
int r = 0;
+ /* Caller must hold vm->root.bo reservation */
+ dma_resv_assert_held(queue->vm->root.bo->tbo.base.resv);
+
user_addr = (addr & AMDGPU_GMC_HOLE_MASK) >> AMDGPU_GPU_PAGE_SHIFT;
size = expected_size >> AMDGPU_GPU_PAGE_SHIFT;
- r = amdgpu_bo_reserve(vm->root.bo, false);
- if (r)
- return r;
-
va_map = amdgpu_vm_bo_lookup_mapping(vm, user_addr);
if (!va_map) {
r = -EINVAL;
@@ -255,13 +254,11 @@ int amdgpu_userq_input_va_validate(struct amdgpu_device *adev,
if (user_addr >= va_map->start &&
va_map->last - user_addr + 1 >= size) {
amdgpu_userq_buffer_va_list_add(queue, va_map, user_addr);
- amdgpu_bo_unreserve(vm->root.bo);
return 0;
}
r = -EINVAL;
out_err:
- amdgpu_bo_unreserve(vm->root.bo);
return r;
}
@@ -270,15 +267,13 @@ static bool amdgpu_userq_buffer_va_mapped(struct amdgpu_vm *vm, u64 addr)
struct amdgpu_bo_va_mapping *mapping;
bool r;
- if (amdgpu_bo_reserve(vm->root.bo, false))
- return false;
+ dma_resv_assert_held(vm->root.bo->tbo.base.resv);
mapping = amdgpu_vm_bo_lookup_mapping(vm, addr);
if (!IS_ERR_OR_NULL(mapping) && atomic_read(&mapping->bo_va->userq_va_mapped))
r = true;
else
r = false;
- amdgpu_bo_unreserve(vm->root.bo);
return r;
}
@@ -314,25 +309,21 @@ static int amdgpu_userq_buffer_vas_list_cleanup(struct amdgpu_device *adev,
{
struct amdgpu_userq_va_cursor *va_cursor, *tmp;
struct amdgpu_bo_va_mapping *mapping;
- int r;
- r = amdgpu_bo_reserve(queue->vm->root.bo, false);
- if (r)
- return r;
+ /* Caller must hold vm->root.bo reservation */
+ dma_resv_assert_held(queue->vm->root.bo->tbo.base.resv);
list_for_each_entry_safe(va_cursor, tmp, &queue->userq_va_list, list) {
mapping = amdgpu_vm_bo_lookup_mapping(queue->vm, va_cursor->gpu_addr);
if (!mapping) {
- r = -EINVAL;
- goto err;
+ return -EINVAL;
}
dev_dbg(adev->dev, "delete the userq:%p va:%llx\n",
queue, va_cursor->gpu_addr);
amdgpu_userq_buffer_va_list_del(mapping, va_cursor);
}
-err:
- amdgpu_bo_unreserve(queue->vm->root.bo);
- return r;
+
+ return 0;
}
static int amdgpu_userq_preempt_helper(struct amdgpu_usermode_queue *queue)
@@ -446,8 +437,6 @@ static void amdgpu_userq_cleanup(struct amdgpu_usermode_queue *queue)
/* Wait for mode-1 reset to complete */
down_read(&adev->reset_domain->sem);
- /* Drop the userq reference. */
- amdgpu_userq_buffer_vas_list_cleanup(adev, queue);
uq_funcs->mqd_destroy(queue);
/* Use interrupt-safe locking since IRQ handlers may access these XArrays */
xa_erase_irq(&adev->userq_doorbell_xa, queue->doorbell_index);
@@ -455,11 +444,19 @@ static void amdgpu_userq_cleanup(struct amdgpu_usermode_queue *queue)
queue->fence_drv = NULL;
queue->userq_mgr = NULL;
list_del(&queue->userq_va_list);
- kfree(queue);
up_read(&adev->reset_domain->sem);
}
+/**
+ * amdgpu_userq_ensure_ev_fence - ensure a valid, unsignaled eviction fence exists
+ * @uq_mgr: the usermode queue manager for this process
+ * @evf_mgr: the eviction fence manager to check and rearm
+ *
+ * Ensures that a valid and not yet signaled eviction fence is attached to the
+ * usermode queue before any queue operations proceed. If it is signalled, then
+ * rearm a new eviction fence.
+ */
void
amdgpu_userq_ensure_ev_fence(struct amdgpu_userq_mgr *uq_mgr,
struct amdgpu_eviction_fence_mgr *evf_mgr)
@@ -619,6 +616,9 @@ static int
amdgpu_userq_destroy(struct amdgpu_userq_mgr *uq_mgr, struct amdgpu_usermode_queue *queue)
{
struct amdgpu_device *adev = uq_mgr->adev;
+ struct amdgpu_fpriv *fpriv = uq_mgr_to_fpriv(uq_mgr);
+ struct amdgpu_vm *vm = &fpriv->vm;
+
int r = 0;
cancel_delayed_work_sync(&uq_mgr->resume_work);
@@ -626,38 +626,44 @@ amdgpu_userq_destroy(struct amdgpu_userq_mgr *uq_mgr, struct amdgpu_usermode_que
/* Cancel any pending hang detection work and cleanup */
cancel_delayed_work_sync(&queue->hang_detect_work);
+ r = amdgpu_bo_reserve(vm->root.bo, false);
+ if (r) {
+ drm_file_err(uq_mgr->file, "Failed to reserve root bo during userqueue destroy\n");
+ return r;
+ }
+ amdgpu_userq_buffer_vas_list_cleanup(adev, queue);
+ amdgpu_bo_unreserve(vm->root.bo);
+
mutex_lock(&uq_mgr->userq_mutex);
queue->hang_detect_fence = NULL;
amdgpu_userq_wait_for_last_fence(queue);
- r = amdgpu_bo_reserve(queue->db_obj.obj, true);
- if (!r) {
- amdgpu_bo_unpin(queue->db_obj.obj);
- amdgpu_bo_unreserve(queue->db_obj.obj);
- }
- amdgpu_bo_unref(&queue->db_obj.obj);
-
- r = amdgpu_bo_reserve(queue->wptr_obj.obj, true);
- if (!r) {
- amdgpu_bo_unpin(queue->wptr_obj.obj);
- amdgpu_bo_unreserve(queue->wptr_obj.obj);
- }
- amdgpu_bo_unref(&queue->wptr_obj.obj);
-
- atomic_dec(&uq_mgr->userq_count[queue->queue_type]);
#if defined(CONFIG_DEBUG_FS)
debugfs_remove_recursive(queue->debugfs_queue);
#endif
amdgpu_userq_detect_and_reset_queues(uq_mgr);
r = amdgpu_userq_unmap_helper(queue);
/*TODO: It requires a reset for userq hw unmap error*/
- if (unlikely(r != AMDGPU_USERQ_STATE_UNMAPPED)) {
+ if (r) {
drm_warn(adev_to_drm(uq_mgr->adev), "trying to destroy a HW mapping userq\n");
queue->state = AMDGPU_USERQ_STATE_HUNG;
}
+
+ atomic_dec(&uq_mgr->userq_count[queue->queue_type]);
amdgpu_userq_cleanup(queue);
mutex_unlock(&uq_mgr->userq_mutex);
+ amdgpu_bo_reserve(queue->db_obj.obj, true);
+ amdgpu_bo_unpin(queue->db_obj.obj);
+ amdgpu_bo_unreserve(queue->db_obj.obj);
+ amdgpu_bo_unref(&queue->db_obj.obj);
+
+ amdgpu_bo_reserve(queue->wptr_obj.obj, true);
+ amdgpu_bo_unpin(queue->wptr_obj.obj);
+ amdgpu_bo_unreserve(queue->wptr_obj.obj);
+ amdgpu_bo_unref(&queue->wptr_obj.obj);
+ kfree(queue);
+
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
return r;
@@ -730,35 +736,25 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
if (r)
return r;
- r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
+ r = pm_runtime_resume_and_get(adev_to_drm(adev)->dev);
if (r < 0) {
- drm_file_err(uq_mgr->file, "pm_runtime_get_sync() failed for userqueue create\n");
- pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
+ drm_file_err(uq_mgr->file, "pm_runtime_resume_and_get() failed for userqueue create\n");
return r;
}
- /*
- * There could be a situation that we are creating a new queue while
- * the other queues under this UQ_mgr are suspended. So if there is any
- * resume work pending, wait for it to get done.
- *
- * This will also make sure we have a valid eviction fence ready to be used.
- */
- amdgpu_userq_ensure_ev_fence(&fpriv->userq_mgr, &fpriv->evf_mgr);
-
uq_funcs = adev->userq_funcs[args->in.ip_type];
if (!uq_funcs) {
drm_file_err(uq_mgr->file, "Usermode queue is not supported for this IP (%u)\n",
args->in.ip_type);
r = -EINVAL;
- goto unlock;
+ goto err_pm_runtime;
}
queue = kzalloc_obj(struct amdgpu_usermode_queue);
if (!queue) {
drm_file_err(uq_mgr->file, "Failed to allocate memory for queue\n");
r = -ENOMEM;
- goto unlock;
+ goto err_pm_runtime;
}
INIT_LIST_HEAD(&queue->userq_va_list);
@@ -773,20 +769,27 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
db_info.doorbell_offset = args->in.doorbell_offset;
queue->userq_mgr = uq_mgr;
+
/* Validate the userq virtual address.*/
+ r = amdgpu_bo_reserve(fpriv->vm.root.bo, false);
+ if (r)
+ goto free_queue;
+
if (amdgpu_userq_input_va_validate(adev, queue, args->in.queue_va, args->in.queue_size) ||
amdgpu_userq_input_va_validate(adev, queue, args->in.rptr_va, AMDGPU_GPU_PAGE_SIZE) ||
amdgpu_userq_input_va_validate(adev, queue, args->in.wptr_va, AMDGPU_GPU_PAGE_SIZE)) {
r = -EINVAL;
- goto free_queue;
+ amdgpu_bo_unreserve(fpriv->vm.root.bo);
+ goto clean_mapping;
}
+ amdgpu_bo_unreserve(fpriv->vm.root.bo);
/* Convert relative doorbell offset into absolute doorbell index */
index = amdgpu_userq_get_doorbell_index(uq_mgr, &db_info, filp);
if (index == (uint64_t)-EINVAL) {
drm_file_err(uq_mgr->file, "Failed to get doorbell for queue\n");
r = -EINVAL;
- goto free_queue;
+ goto clean_mapping;
}
queue->doorbell_index = index;
@@ -794,7 +797,7 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
r = amdgpu_userq_fence_driver_alloc(adev, &queue->fence_drv);
if (r) {
drm_file_err(uq_mgr->file, "Failed to alloc fence driver\n");
- goto free_queue;
+ goto clean_mapping;
}
r = uq_funcs->mqd_create(queue, &args->in);
@@ -803,6 +806,8 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
goto clean_fence_driver;
}
+ amdgpu_userq_ensure_ev_fence(&fpriv->userq_mgr, &fpriv->evf_mgr);
+
/* don't map the queue if scheduling is halted */
if (adev->userq_halt_for_enforce_isolation &&
((queue->queue_type == AMDGPU_HW_IP_GFX) ||
@@ -814,7 +819,6 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
r = amdgpu_userq_map_helper(queue);
if (r) {
drm_file_err(uq_mgr->file, "Failed to map Queue\n");
- down_read(&adev->reset_domain->sem);
goto clean_mqd;
}
}
@@ -830,9 +834,8 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
if (r) {
if (!skip_map_queue)
amdgpu_userq_unmap_helper(queue);
-
r = -ENOMEM;
- goto clean_mqd;
+ goto clean_reset_domain;
}
r = xa_err(xa_store_irq(&adev->userq_doorbell_xa, index, queue, GFP_KERNEL));
@@ -840,8 +843,7 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
xa_erase(&uq_mgr->userq_xa, qid);
if (!skip_map_queue)
amdgpu_userq_unmap_helper(queue);
-
- goto clean_mqd;
+ goto clean_reset_domain;
}
up_read(&adev->reset_domain->sem);
@@ -853,16 +855,21 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
mutex_unlock(&uq_mgr->userq_mutex);
return 0;
+clean_reset_domain:
+ up_read(&adev->reset_domain->sem);
clean_mqd:
+ mutex_unlock(&uq_mgr->userq_mutex);
uq_funcs->mqd_destroy(queue);
- up_read(&adev->reset_domain->sem);
clean_fence_driver:
amdgpu_userq_fence_driver_free(queue);
+clean_mapping:
+ amdgpu_bo_reserve(fpriv->vm.root.bo, true);
+ amdgpu_userq_buffer_vas_list_cleanup(adev, queue);
+ amdgpu_bo_unreserve(fpriv->vm.root.bo);
free_queue:
kfree(queue);
-unlock:
- mutex_unlock(&uq_mgr->userq_mutex);
-
+err_pm_runtime:
+ pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
return r;
}
@@ -992,10 +999,16 @@ int amdgpu_userq_ioctl(struct drm_device *dev, void *data,
static int
amdgpu_userq_restore_all(struct amdgpu_userq_mgr *uq_mgr)
{
+ struct amdgpu_fpriv *fpriv = uq_mgr_to_fpriv(uq_mgr);
+ struct amdgpu_vm *vm = &fpriv->vm;
struct amdgpu_usermode_queue *queue;
unsigned long queue_id;
int ret = 0, r;
+
+ if (amdgpu_bo_reserve(vm->root.bo, false))
+ return false;
+
mutex_lock(&uq_mgr->userq_mutex);
/* Resume all the queues for this process */
xa_for_each(&uq_mgr->userq_xa, queue_id, queue) {
@@ -1013,6 +1026,7 @@ amdgpu_userq_restore_all(struct amdgpu_userq_mgr *uq_mgr)
}
mutex_unlock(&uq_mgr->userq_mutex);
+ amdgpu_bo_unreserve(vm->root.bo);
if (ret)
drm_file_err(uq_mgr->file,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
index 5784f2b3ecae..da39ac862f37 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
@@ -145,13 +145,22 @@ amdgpu_userq_fence_driver_free(struct amdgpu_usermode_queue *userq)
amdgpu_userq_fence_driver_put(userq->fence_drv);
}
+static void
+amdgpu_userq_fence_put_fence_drv_array(struct amdgpu_userq_fence *userq_fence)
+{
+ unsigned long i;
+ for (i = 0; i < userq_fence->fence_drv_array_count; i++)
+ amdgpu_userq_fence_driver_put(userq_fence->fence_drv_array[i]);
+ userq_fence->fence_drv_array_count = 0;
+}
+
void amdgpu_userq_fence_driver_process(struct amdgpu_userq_fence_driver *fence_drv)
{
struct amdgpu_userq_fence *userq_fence, *tmp;
+ LIST_HEAD(to_be_signaled);
struct dma_fence *fence;
unsigned long flags;
u64 rptr;
- int i;
if (!fence_drv)
return;
@@ -159,21 +168,26 @@ void amdgpu_userq_fence_driver_process(struct amdgpu_userq_fence_driver *fence_d
spin_lock_irqsave(&fence_drv->fence_list_lock, flags);
rptr = amdgpu_userq_fence_read(fence_drv);
- list_for_each_entry_safe(userq_fence, tmp, &fence_drv->fences, link) {
- fence = &userq_fence->base;
-
- if (rptr < fence->seqno)
+ list_for_each_entry(userq_fence, &fence_drv->fences, link) {
+ if (rptr < userq_fence->base.seqno)
break;
+ }
- dma_fence_signal(fence);
-
- for (i = 0; i < userq_fence->fence_drv_array_count; i++)
- amdgpu_userq_fence_driver_put(userq_fence->fence_drv_array[i]);
+ list_cut_before(&to_be_signaled, &fence_drv->fences,
+ &userq_fence->link);
+ spin_unlock_irqrestore(&fence_drv->fence_list_lock, flags);
- list_del(&userq_fence->link);
+ list_for_each_entry_safe(userq_fence, tmp, &to_be_signaled, link) {
+ fence = &userq_fence->base;
+ list_del_init(&userq_fence->link);
+ dma_fence_signal(fence);
+ /* Drop fence_drv_array outside fence_list_lock
+ * to avoid the recursion lock.
+ */
+ amdgpu_userq_fence_put_fence_drv_array(userq_fence);
dma_fence_put(fence);
}
- spin_unlock_irqrestore(&fence_drv->fence_list_lock, flags);
+
}
void amdgpu_userq_fence_driver_destroy(struct kref *ref)
@@ -228,6 +242,7 @@ static int amdgpu_userq_fence_create(struct amdgpu_usermode_queue *userq,
struct amdgpu_userq_fence_driver *fence_drv;
struct dma_fence *fence;
unsigned long flags;
+ bool signaled = false;
fence_drv = userq->fence_drv;
if (!fence_drv)
@@ -274,13 +289,17 @@ static int amdgpu_userq_fence_create(struct amdgpu_usermode_queue *userq,
/* Check if hardware has already processed the job */
spin_lock_irqsave(&fence_drv->fence_list_lock, flags);
- if (!dma_fence_is_signaled(fence))
+ if (!dma_fence_is_signaled(fence)) {
list_add_tail(&userq_fence->link, &fence_drv->fences);
- else
+ } else {
+ signaled = true;
dma_fence_put(fence);
-
+ }
spin_unlock_irqrestore(&fence_drv->fence_list_lock, flags);
+ if (signaled)
+ amdgpu_userq_fence_put_fence_drv_array(userq_fence);
+
*f = fence;
return 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
index 03d95dca93d7..debb82a2e031 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
@@ -34,6 +34,7 @@
#include "amdgpu.h"
#include "amdgpu_pm.h"
#include "amdgpu_vcn.h"
+#include "amdgpu_reset.h"
#include "soc15d.h"
/* Firmware Names */
@@ -361,7 +362,7 @@ int amdgpu_vcn_suspend(struct amdgpu_device *adev, int i)
/* err_event_athub and dpc recovery will corrupt VCPU buffer, so we need to
* restore fw data and clear buffer in amdgpu_vcn_resume() */
- if (in_ras_intr || adev->pcie_reset_ctx.in_link_reset)
+ if (in_ras_intr || amdgpu_reset_in_dpc(adev))
return 0;
return amdgpu_vcn_save_vcpu_bo_inst(adev, i);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_cpu.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_cpu.c
index 22e2e5b47341..f078db3fef79 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_cpu.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_cpu.c
@@ -21,6 +21,8 @@
*/
#include "amdgpu_vm.h"
+#include "amdgpu.h"
+#include "amdgpu_reset.h"
#include "amdgpu_object.h"
#include "amdgpu_trace.h"
@@ -108,11 +110,19 @@ static int amdgpu_vm_cpu_update(struct amdgpu_vm_update_params *p,
static int amdgpu_vm_cpu_commit(struct amdgpu_vm_update_params *p,
struct dma_fence **fence)
{
+ struct amdgpu_device *adev = p->adev;
+
if (p->needs_flush)
atomic64_inc(&p->vm->tlb_seq);
mb();
- amdgpu_device_flush_hdp(p->adev, NULL);
+ /* A reset flushed the HDP anyway, so that here can be skipped when a reset is ongoing */
+ if (!down_read_trylock(&adev->reset_domain->sem))
+ return 0;
+
+ amdgpu_device_flush_hdp(adev, NULL);
+ up_read(&adev->reset_domain->sem);
+
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
index 31a437ce9570..a930f1522f96 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
@@ -693,8 +693,11 @@ static void amdgpu_vm_pte_update_flags(struct amdgpu_vm_update_params *params,
!(flags & AMDGPU_PTE_VALID) &&
!(flags & AMDGPU_PTE_PRT_FLAG(params->adev))) {
- /* Workaround for fault priority problem on GMC9 */
- flags |= AMDGPU_PTE_EXECUTABLE;
+ /* Workaround for fault priority problem on GMC9 and GFX12,
+ * EXECUTABLE for GMC9 fault priority and init_pte_flags
+ * (e.g. AMDGPU_PTE_IS_PTE on GFX12)
+ */
+ flags |= AMDGPU_PTE_EXECUTABLE | adev->gmc.init_pte_flags;
}
/*
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
index 5097de940a19..8c82e90f871b 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
@@ -64,6 +64,11 @@
#define regPC_CONFIG_CNTL_1 0x194d
#define regPC_CONFIG_CNTL_1_BASE_IDX 1
+#define regGOLDEN_TSC_COUNT_UPPER_smu_15_0_0 0x0030
+#define regGOLDEN_TSC_COUNT_UPPER_smu_15_0_0_BASE_IDX 1
+#define regGOLDEN_TSC_COUNT_LOWER_smu_15_0_0 0x0031
+#define regGOLDEN_TSC_COUNT_LOWER_smu_15_0_0_BASE_IDX 1
+
#define regCP_GFX_MQD_CONTROL_DEFAULT 0x00000100
#define regCP_GFX_HQD_VMID_DEFAULT 0x00000000
#define regCP_GFX_HQD_QUEUE_PRIORITY_DEFAULT 0x00000000
@@ -5234,11 +5239,27 @@ static uint64_t gfx_v11_0_get_gpu_clock_counter(struct amdgpu_device *adev)
amdgpu_gfx_off_ctrl(adev, true);
} else {
preempt_disable();
- clock_counter_hi_pre = (uint64_t)RREG32_SOC15(SMUIO, 0, regGOLDEN_TSC_COUNT_UPPER);
- clock_counter_lo = (uint64_t)RREG32_SOC15(SMUIO, 0, regGOLDEN_TSC_COUNT_LOWER);
- clock_counter_hi_after = (uint64_t)RREG32_SOC15(SMUIO, 0, regGOLDEN_TSC_COUNT_UPPER);
- if (clock_counter_hi_pre != clock_counter_hi_after)
- clock_counter_lo = (uint64_t)RREG32_SOC15(SMUIO, 0, regGOLDEN_TSC_COUNT_LOWER);
+ if (amdgpu_ip_version(adev, SMUIO_HWIP, 0) < IP_VERSION(15, 0, 0)) {
+ clock_counter_hi_pre = (uint64_t)RREG32_SOC15(SMUIO, 0,
+ regGOLDEN_TSC_COUNT_UPPER);
+ clock_counter_lo = (uint64_t)RREG32_SOC15(SMUIO, 0,
+ regGOLDEN_TSC_COUNT_LOWER);
+ clock_counter_hi_after = (uint64_t)RREG32_SOC15(SMUIO, 0,
+ regGOLDEN_TSC_COUNT_UPPER);
+ if (clock_counter_hi_pre != clock_counter_hi_after)
+ clock_counter_lo = (uint64_t)RREG32_SOC15(SMUIO, 0,
+ regGOLDEN_TSC_COUNT_LOWER);
+ } else {
+ clock_counter_hi_pre = (uint64_t)RREG32_SOC15(SMUIO, 0,
+ regGOLDEN_TSC_COUNT_UPPER_smu_15_0_0);
+ clock_counter_lo = (uint64_t)RREG32_SOC15(SMUIO, 0,
+ regGOLDEN_TSC_COUNT_LOWER_smu_15_0_0);
+ clock_counter_hi_after = (uint64_t)RREG32_SOC15(SMUIO, 0,
+ regGOLDEN_TSC_COUNT_UPPER_smu_15_0_0);
+ if (clock_counter_hi_pre != clock_counter_hi_after)
+ clock_counter_lo = (uint64_t)RREG32_SOC15(SMUIO, 0,
+ regGOLDEN_TSC_COUNT_LOWER_smu_15_0_0);
+ }
preempt_enable();
}
clock = clock_counter_lo | (clock_counter_hi_after << 32ULL);
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c
index 4b4aa9553624..82abe181c730 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c
@@ -736,15 +736,35 @@ static void jpeg_v4_0_3_dec_ring_set_wptr(struct amdgpu_ring *ring)
*/
void jpeg_v4_0_3_dec_ring_insert_start(struct amdgpu_ring *ring)
{
- if (!amdgpu_sriov_vf(ring->adev)) {
+ struct amdgpu_device *adev = ring->adev;
+
+ if (!amdgpu_sriov_vf(adev)) {
+ int jpeg_inst = GET_INST(JPEG, ring->me);
+ uint32_t value = 0x80004000; /* default DS14 */
+
amdgpu_ring_write(ring, PACKETJ(regUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET,
0, 0, PACKETJ_TYPE0));
- amdgpu_ring_write(ring, 0x62a04); /* PCTL0_MMHUB_DEEPSLEEP_IB */
+
+ /* PCTL0__MMHUB_DEEPSLEEP_IB could be different on different mmhub version */
+ switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
+ case IP_VERSION(4, 1, 0):
+ amdgpu_ring_write(ring, 0x69004);
+ value = 0x80010000;
+ break;
+ case IP_VERSION(4, 2, 0):
+ amdgpu_ring_write(ring, 0x60804);
+ if (jpeg_inst & 1)
+ value = 0x80010000;
+ break;
+ default:
+ amdgpu_ring_write(ring, 0x62a04);
+ break;
+ }
amdgpu_ring_write(ring,
PACKETJ(JRBC_DEC_EXTERNAL_REG_WRITE_ADDR, 0,
0, PACKETJ_TYPE0));
- amdgpu_ring_write(ring, 0x80004000);
+ amdgpu_ring_write(ring, value);
}
}
@@ -757,15 +777,35 @@ void jpeg_v4_0_3_dec_ring_insert_start(struct amdgpu_ring *ring)
*/
void jpeg_v4_0_3_dec_ring_insert_end(struct amdgpu_ring *ring)
{
- if (!amdgpu_sriov_vf(ring->adev)) {
+ struct amdgpu_device *adev = ring->adev;
+
+ if (!amdgpu_sriov_vf(adev)) {
+ int jpeg_inst = GET_INST(JPEG, ring->me);
+ uint32_t value = 0x00004000; /* default DS14 */
+
amdgpu_ring_write(ring, PACKETJ(regUVD_JRBC_EXTERNAL_REG_INTERNAL_OFFSET,
0, 0, PACKETJ_TYPE0));
- amdgpu_ring_write(ring, 0x62a04);
+
+ /* PCTL0__MMHUB_DEEPSLEEP_IB could be different on different mmhub version */
+ switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
+ case IP_VERSION(4, 1, 0):
+ amdgpu_ring_write(ring, 0x69004);
+ value = 0x00010000;
+ break;
+ case IP_VERSION(4, 2, 0):
+ amdgpu_ring_write(ring, 0x60804);
+ if (jpeg_inst & 1)
+ value = 0x00010000;
+ break;
+ default:
+ amdgpu_ring_write(ring, 0x62a04);
+ break;
+ }
amdgpu_ring_write(ring,
PACKETJ(JRBC_DEC_EXTERNAL_REG_WRITE_ADDR, 0,
0, PACKETJ_TYPE0));
- amdgpu_ring_write(ring, 0x00004000);
+ amdgpu_ring_write(ring, value);
}
}
diff --git a/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c b/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c
index faac21ee5739..2fc39a6938f6 100644
--- a/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c
+++ b/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c
@@ -322,8 +322,14 @@ static int mes_userq_mqd_create(struct amdgpu_usermode_queue *queue,
goto free_mqd;
}
+ r = amdgpu_bo_reserve(queue->vm->root.bo, false);
+ if (r) {
+ kfree(compute_mqd);
+ goto free_mqd;
+ }
r = amdgpu_userq_input_va_validate(adev, queue, compute_mqd->eop_va,
2048);
+ amdgpu_bo_unreserve(queue->vm->root.bo);
if (r) {
kfree(compute_mqd);
goto free_mqd;
@@ -365,14 +371,22 @@ static int mes_userq_mqd_create(struct amdgpu_usermode_queue *queue,
userq_props->tmz_queue =
mqd_user->flags & AMDGPU_USERQ_CREATE_FLAGS_QUEUE_SECURE;
+ r = amdgpu_bo_reserve(queue->vm->root.bo, false);
+ if (r) {
+ kfree(mqd_gfx_v11);
+ goto free_mqd;
+ }
r = amdgpu_userq_input_va_validate(adev, queue, mqd_gfx_v11->shadow_va,
shadow_info.shadow_size);
if (r) {
+ amdgpu_bo_unreserve(queue->vm->root.bo);
kfree(mqd_gfx_v11);
goto free_mqd;
}
+
r = amdgpu_userq_input_va_validate(adev, queue, mqd_gfx_v11->csa_va,
shadow_info.csa_size);
+ amdgpu_bo_unreserve(queue->vm->root.bo);
if (r) {
kfree(mqd_gfx_v11);
goto free_mqd;
@@ -394,8 +408,15 @@ static int mes_userq_mqd_create(struct amdgpu_usermode_queue *queue,
r = -ENOMEM;
goto free_mqd;
}
+
+ r = amdgpu_bo_reserve(queue->vm->root.bo, false);
+ if (r) {
+ kfree(mqd_sdma_v11);
+ goto free_mqd;
+ }
r = amdgpu_userq_input_va_validate(adev, queue, mqd_sdma_v11->csa_va,
32);
+ amdgpu_bo_unreserve(queue->vm->root.bo);
if (r) {
kfree(mqd_sdma_v11);
goto free_mqd;
diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v12_1.c b/drivers/gpu/drm/amd/amdgpu/mes_v12_1.c
index 0e9089544769..cec801278126 100644
--- a/drivers/gpu/drm/amd/amdgpu/mes_v12_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/mes_v12_1.c
@@ -2028,7 +2028,7 @@ static int mes_v12_1_test_ring(struct amdgpu_device *adev, int xcc_id,
int num_xcc = NUM_XCC(adev->gfx.xcc_mask);
int sdma_ring_align = 0x10, compute_ring_align = 0x100;
uint32_t tmp, xcc_offset;
- int r = 0, i, wptr = 0;
+ int r = 0, i, j, wptr = 0;
if (queue_type == AMDGPU_RING_TYPE_COMPUTE) {
if (!adev->mes.enable_coop_mode) {
@@ -2077,11 +2077,11 @@ static int mes_v12_1_test_ring(struct amdgpu_device *adev, int xcc_id,
tmp = RREG32_SOC15(GC, GET_INST(GC, xcc_id),
regSCRATCH_REG0);
} else {
- for (i = 0; i < num_xcc; i++) {
- if (xcc_id != adev->mes.master_xcc_ids[i])
+ for (j = 0; j < num_xcc; j++) {
+ if (xcc_id != adev->mes.master_xcc_ids[j])
continue;
- tmp = RREG32_SOC15(GC, GET_INST(GC, i),
+ tmp = RREG32_SOC15(GC, GET_INST(GC, j),
regSCRATCH_REG0);
if (tmp != 0xDEADBEEF)
break;
diff --git a/drivers/gpu/drm/amd/amdgpu/nbif_v6_3_1.c b/drivers/gpu/drm/amd/amdgpu/nbif_v6_3_1.c
index db14a1a326d2..b6f832c53860 100644
--- a/drivers/gpu/drm/amd/amdgpu/nbif_v6_3_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/nbif_v6_3_1.c
@@ -54,6 +54,8 @@
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_5_CTRL_nbif_4_10_BASE_IDX 3
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_5_CTRL1_nbif_4_10 0x4f0af6
#define regGDC_S2A0_S2A_DOORBELL_ENTRY_5_CTRL1_nbif_4_10_BASE_IDX 3
+#define regRCC_STRAP0_RCC_DEV0_EPF0_STRAP0_nbif_4_10 0x0021
+#define regRCC_STRAP0_RCC_DEV0_EPF0_STRAP0_nbif_4_10_BASE_IDX 2
static void nbif_v6_3_1_remap_hdp_registers(struct amdgpu_device *adev)
{
@@ -65,7 +67,12 @@ static void nbif_v6_3_1_remap_hdp_registers(struct amdgpu_device *adev)
static u32 nbif_v6_3_1_get_rev_id(struct amdgpu_device *adev)
{
- u32 tmp = RREG32_SOC15(NBIO, 0, regRCC_STRAP0_RCC_DEV0_EPF0_STRAP0);
+ u32 tmp;
+
+ if (amdgpu_ip_version(adev, NBIO_HWIP, 0) == IP_VERSION(7, 11, 4))
+ tmp = RREG32_SOC15(NBIO, 0, regRCC_STRAP0_RCC_DEV0_EPF0_STRAP0_nbif_4_10);
+ else
+ tmp = RREG32_SOC15(NBIO, 0, regRCC_STRAP0_RCC_DEV0_EPF0_STRAP0);
tmp &= RCC_STRAP0_RCC_DEV0_EPF0_STRAP0__STRAP_ATI_REV_ID_DEV0_F0_MASK;
tmp >>= RCC_STRAP0_RCC_DEV0_EPF0_STRAP0__STRAP_ATI_REV_ID_DEV0_F0__SHIFT;
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v15_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v15_0.c
index 73a709773e85..2a8582e87f2b 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v15_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v15_0.c
@@ -32,6 +32,7 @@
#include "mp/mp_15_0_0_sh_mask.h"
MODULE_FIRMWARE("amdgpu/psp_15_0_0_toc.bin");
+MODULE_FIRMWARE("amdgpu/psp_15_0_0_ta.bin");
static int psp_v15_0_0_init_microcode(struct psp_context *psp)
{
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v7_1.c b/drivers/gpu/drm/amd/amdgpu/sdma_v7_1.c
index f20e0fc3fc74..061934a2e93a 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v7_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v7_1.c
@@ -1268,6 +1268,18 @@ static int sdma_v7_1_early_init(struct amdgpu_ip_block *ip_block)
struct amdgpu_device *adev = ip_block->adev;
int r;
+ switch (amdgpu_user_queue) {
+ case -1:
+ default:
+ adev->sdma.no_user_submission = true;
+ adev->sdma.disable_uq = true;
+ break;
+ case 0:
+ adev->sdma.no_user_submission = false;
+ adev->sdma.disable_uq = true;
+ break;
+ }
+
r = amdgpu_sdma_init_microcode(adev, 0, true);
if (r) {
DRM_ERROR("Failed to init sdma firmware!\n");