summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/amdgpu
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c62
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_device.c9
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_object.c13
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c20
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c21
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c10
9 files changed, 112 insertions, 38 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
index aa039e148a5e..8525c45ab209 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
@@ -372,19 +372,59 @@ static bool amdgpu_read_disabled_bios(struct amdgpu_device *adev)
}
#ifdef CONFIG_ACPI
+/**
+ * amdgpu_acpi_vfct_match() - Check if a VFCT entry matches the device
+ * @adev: AMDGPU device
+ * @vhdr: VFCT image header to check
+ *
+ * VFCT entries contain the PCI bus number as recorded during BIOS POST.
+ * On systems where the kernel renumbers PCI buses (e.g. pci=realloc or
+ * resource conflicts), the runtime bus number may differ from the POST
+ * value. Match by device identity (vendor + device + function) and use
+ * the bus number as a preference: exact bus match is preferred, but when
+ * the bus numbers disagree we accept the entry if the device identity
+ * matches.
+ *
+ * Returns: 0 on match, -ENODEV on no match
+ */
+static int amdgpu_acpi_vfct_match(struct amdgpu_device *adev,
+ VFCT_IMAGE_HEADER *vhdr)
+{
+ /* Vendor and device IDs must always match */
+ if (vhdr->VendorID != adev->pdev->vendor ||
+ vhdr->DeviceID != adev->pdev->device)
+ return -ENODEV;
+
+ if (vhdr->PCIDevice != PCI_SLOT(adev->pdev->devfn) ||
+ vhdr->PCIFunction != PCI_FUNC(adev->pdev->devfn))
+ return -ENODEV;
+
+ /* Exact bus number match - preferred */
+ if (vhdr->PCIBus == adev->pdev->bus->number)
+ return 0;
+
+ /* Bus mismatch but device identity matches (PCI renumbering case) */
+ dev_notice(adev->dev,
+ "VFCT bus number mismatch: table %u != runtime %u, matching by device identity (vendor 0x%04x device 0x%04x)\n",
+ vhdr->PCIBus, adev->pdev->bus->number,
+ adev->pdev->vendor, adev->pdev->device);
+ return 0;
+}
+
static bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev)
{
struct acpi_table_header *hdr;
acpi_size tbl_size;
UEFI_ACPI_VFCT *vfct;
unsigned int offset;
+ bool r = false;
if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr)))
return false;
tbl_size = hdr->length;
if (tbl_size < sizeof(UEFI_ACPI_VFCT)) {
dev_info(adev->dev, "ACPI VFCT table present but broken (too short #1),skipping\n");
- return false;
+ goto out;
}
vfct = (UEFI_ACPI_VFCT *)hdr;
@@ -397,36 +437,36 @@ static bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev)
offset += sizeof(VFCT_IMAGE_HEADER);
if (offset > tbl_size) {
dev_info(adev->dev, "ACPI VFCT image header truncated,skipping\n");
- return false;
+ goto out;
}
offset += vhdr->ImageLength;
if (offset > tbl_size) {
dev_info(adev->dev, "ACPI VFCT image truncated,skipping\n");
- return false;
+ goto out;
}
if (vhdr->ImageLength &&
- vhdr->PCIBus == adev->pdev->bus->number &&
- vhdr->PCIDevice == PCI_SLOT(adev->pdev->devfn) &&
- vhdr->PCIFunction == PCI_FUNC(adev->pdev->devfn) &&
- vhdr->VendorID == adev->pdev->vendor &&
- vhdr->DeviceID == adev->pdev->device) {
+ !amdgpu_acpi_vfct_match(adev, vhdr)) {
adev->bios = kmemdup(&vbios->VbiosContent,
vhdr->ImageLength,
GFP_KERNEL);
if (!check_atom_bios(adev, vhdr->ImageLength)) {
amdgpu_bios_release(adev);
- return false;
+ goto out;
}
adev->bios_size = vhdr->ImageLength;
- return true;
+ r = true;
+ goto out;
}
}
dev_info(adev->dev, "ACPI VFCT table present but broken (too short #2),skipping\n");
- return false;
+
+out:
+ acpi_put_table(hdr);
+ return r;
}
#else
static inline bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c
index e77db76b48b8..6480a344006d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c
@@ -234,6 +234,9 @@ amdgpu_devcoredump_print_ibs(struct drm_printer *p,
drm_printf(p, "\nIB #%d 0x%llx %d dw\n", i,
coredump->ibs[i].gpu_addr,
coredump->ibs[i].ib_size_dw);
+
+ for (int j = 0; j < coredump->ibs[i].ib_size_dw; j++)
+ drm_printf(p, "0xffffffff\n");
}
return;
}
@@ -355,10 +358,14 @@ amdgpu_devcoredump_format(char *buffer, size_t count, struct amdgpu_coredump_inf
drm_printf(&p, "kernel: %s\n", init_utsname()->release);
drm_printf(&p, "module: " KBUILD_MODNAME "\n");
drm_printf(&p, "time: %ptSp\n", &coredump->reset_time);
+ drm_printf(&p, "pasid: %u\n", coredump->pasid);
+ drm_printf(&p, "vmid: %u\n", coredump->vmid);
if (coredump->reset_task_info.task.pid)
- drm_printf(&p, "process_name: %s PID: %d\n",
+ drm_printf(&p, "process_name: %s TGID: %d thread: %s PID: %d\n",
coredump->reset_task_info.process_name,
+ coredump->reset_task_info.tgid,
+ coredump->reset_task_info.task.comm,
coredump->reset_task_info.task.pid);
/* SOC Information */
@@ -562,6 +569,7 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check,
amdgpu_vm_put_task_info(ti);
}
coredump->pasid = job->pasid;
+ coredump->vmid = job->vmid;
coredump->num_ibs = job->num_ibs;
for (i = 0; i < job->num_ibs; ++i) {
coredump->ibs[i].gpu_addr = job->ibs[i].gpu_addr;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.h
index 2371e20fc68b..63f27337c09a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.h
@@ -63,6 +63,7 @@ struct amdgpu_coredump_info {
char *formatted;
unsigned int pasid;
+ unsigned int vmid;
int num_ibs;
struct amdgpu_coredump_ib_info ibs[] __counted_by(num_ibs);
};
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 53335ca96b1d..e5f26e5892ba 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -1323,6 +1323,15 @@ static bool amdgpu_device_pcie_dynamic_switching_supported(struct amdgpu_device
if (c->x86_vendor == X86_VENDOR_INTEL)
return false;
+
+ /*
+ * AMD Ryzen Pinnacle Ridge (Zen+, family 0x17 model 0x08) CPUs don't
+ * support PCIe dynamic speed switching.
+ * https://gitlab.freedesktop.org/drm/amd/-/work_items/5436
+ */
+ if (c->x86_vendor == X86_VENDOR_AMD && c->x86 == 0x17 &&
+ c->x86_model == 0x08)
+ return false;
#endif
return true;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
index 7b9bb998906d..2860f12915c0 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
@@ -3137,9 +3137,11 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(11, 5, 3):
case IP_VERSION(11, 5, 4):
case IP_VERSION(11, 5, 6):
+ adev->family = AMDGPU_FAMILY_GC_11_5_0;
+ break;
case IP_VERSION(11, 7, 0):
case IP_VERSION(11, 7, 1):
- adev->family = AMDGPU_FAMILY_GC_11_5_0;
+ adev->family = AMDGPU_FAMILY_GC_11_5_4;
break;
case IP_VERSION(12, 0, 0):
case IP_VERSION(12, 0, 1):
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
index f98bfba59a2c..718937777e53 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
@@ -276,10 +276,12 @@ int amdgpu_bo_create_reserved(struct amdgpu_device *adev,
goto error_free;
}
- r = amdgpu_bo_pin(*bo_ptr, domain);
- if (r) {
- dev_err(adev->dev, "(%d) kernel bo pin failed\n", r);
- goto error_unreserve;
+ if (free) {
+ r = amdgpu_bo_pin(*bo_ptr, domain);
+ if (r) {
+ dev_err(adev->dev, "(%d) kernel bo pin failed\n", r);
+ goto error_unreserve;
+ }
}
r = amdgpu_ttm_alloc_gart(&(*bo_ptr)->tbo);
@@ -302,7 +304,8 @@ int amdgpu_bo_create_reserved(struct amdgpu_device *adev,
return 0;
error_unpin:
- amdgpu_bo_unpin(*bo_ptr);
+ if (free)
+ amdgpu_bo_unpin(*bo_ptr);
error_unreserve:
amdgpu_bo_unreserve(*bo_ptr);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index 025625e7e800..eb8bbfc7e6d9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -2684,12 +2684,22 @@ void amdgpu_sdma_set_buffer_funcs_scheds(struct amdgpu_device *adev,
return;
}
- /* Navi1x's workaround requires us to limit to a single SDMA sched
- * for ttm.
- */
hub = &adev->vmhub[AMDGPU_GFXHUB(0)];
- adev->mman.num_buffer_funcs_scheds = hub->sdma_invalidation_workaround ?
- 1 : n;
+
+ /*
+ * Allow using multiple SDMA schedulers only on GPUs where
+ * we are allowed to do concurrent VM flushes.
+ * This consideration is necessary because all GART windows
+ * are mapped in VMID 0 (the kernel VMID) so each buffer
+ * entity would flush VMID 0 concurrently.
+ *
+ * Also consider the SDMA invalidation workaround on
+ * Navi 1x GPUs, which also prevents us from using
+ * multiple SDMA engines on VMID 0 at the same time.
+ */
+ adev->mman.num_buffer_funcs_scheds =
+ (adev->vm_manager.concurrent_flush &&
+ !hub->sdma_invalidation_workaround) ? n : 1;
}
#if defined(CONFIG_DEBUG_FS)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
index d854343b3734..572f2949cb64 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
@@ -1376,16 +1376,19 @@ void amdgpu_userq_pre_reset(struct amdgpu_device *adev)
/* TODO: We probably need a new lock for the queue state */
xa_for_each(&adev->userq_doorbell_xa, queue_id, queue) {
- if (queue->state != AMDGPU_USERQ_STATE_MAPPED)
- continue;
-
- userq_funcs = adev->userq_funcs[queue->queue_type];
- userq_funcs->unmap(queue);
- /* just mark all queues as hung at this point.
- * if unmap succeeds, we could map again
- * in amdgpu_userq_post_reset() if vram is not lost
+ if (queue->state == AMDGPU_USERQ_STATE_MAPPED) {
+ userq_funcs = adev->userq_funcs[queue->queue_type];
+ userq_funcs->unmap(queue);
+ /* just mark all queues as hung at this point.
+ * if unmap succeeds, we could map again
+ * in amdgpu_userq_post_reset() if vram is not lost
+ */
+ queue->state = AMDGPU_USERQ_STATE_HUNG;
+ }
+ /* Force-complete any pending fence regardless of queue state so
+ * that eviction/suspend and queue teardown waiters don't block
+ * forever on a fence that will never signal after the reset.
*/
- queue->state = AMDGPU_USERQ_STATE_HUNG;
amdgpu_userq_fence_driver_force_completion(queue);
}
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index bb99b7c3a010..f224d33c4bc4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -855,12 +855,10 @@ void amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
job->oa_size);
}
- if (vm_flush_needed || pasid_mapping_needed || cleaner_shader_needed) {
- amdgpu_fence_emit(ring, job->hw_vm_fence, 0);
- fence = &job->hw_vm_fence->base;
- /* get a ref for the job */
- dma_fence_get(fence);
- }
+ amdgpu_fence_emit(ring, job->hw_vm_fence, 0);
+ fence = &job->hw_vm_fence->base;
+ /* get a ref for the job */
+ dma_fence_get(fence);
if (vm_flush_needed) {
mutex_lock(&id_mgr->lock);