Commit 7261c2fc authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'amd-drm-fixes-7.0-2026-03-25' of...

Merge tag 'amd-drm-fixes-7.0-2026-03-25' of https://gitlab.freedesktop.org/agd5f/linux

 into drm-fixes

amd-drm-fixes-7.0-2026-03-25:

amdgpu:
- DSC fix
- Module parameter parsing fix
- PASID reuse fix
- drm_edid leak fix
- SMU 13.x fixes
- SMU 14.x fix
- Fence fix in amdgpu_amdkfd_submit_ib()
- LVDS fixes
- GPU page fault fix for non-4K pages

amdkfd:
- Ordering fix in kfd_ioctl_create_process()

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Alex Deucher <alexander.deucher@amd.com>
Link: https://patch.msgid.link/20260325155600.4184877-1-alexander.deucher@amd.com
parents c3692998 90d239cc
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -692,9 +692,9 @@ int amdgpu_amdkfd_submit_ib(struct amdgpu_device *adev,
		goto err_ib_sched;
	}

	/* Drop the initial kref_init count (see drm_sched_main as example) */
	dma_fence_put(f);
	ret = dma_fence_wait(f, false);
	/* Drop the returned fence reference after the wait completes */
	dma_fence_put(f);

err_ib_sched:
	amdgpu_job_free(job);
+11 −2
Original line number Diff line number Diff line
@@ -4207,7 +4207,8 @@ static void amdgpu_device_xgmi_reset_func(struct work_struct *__work)

static int amdgpu_device_get_job_timeout_settings(struct amdgpu_device *adev)
{
	char *input = amdgpu_lockup_timeout;
	char buf[AMDGPU_MAX_TIMEOUT_PARAM_LENGTH];
	char *input = buf;
	char *timeout_setting = NULL;
	int index = 0;
	long timeout;
@@ -4217,9 +4218,17 @@ static int amdgpu_device_get_job_timeout_settings(struct amdgpu_device *adev)
	adev->gfx_timeout = adev->compute_timeout = adev->sdma_timeout =
		adev->video_timeout = msecs_to_jiffies(2000);

	if (!strnlen(input, AMDGPU_MAX_TIMEOUT_PARAM_LENGTH))
	if (!strnlen(amdgpu_lockup_timeout, AMDGPU_MAX_TIMEOUT_PARAM_LENGTH))
		return 0;

	/*
	 * strsep() destructively modifies its input by replacing delimiters
	 * with '\0'. Use a stack copy so the global module parameter buffer
	 * remains intact for multi-GPU systems where this function is called
	 * once per device.
	 */
	strscpy(buf, amdgpu_lockup_timeout, sizeof(buf));

	while ((timeout_setting = strsep(&input, ",")) &&
	       strnlen(timeout_setting, AMDGPU_MAX_TIMEOUT_PARAM_LENGTH)) {
		ret = kstrtol(timeout_setting, 0, &timeout);
+32 −13
Original line number Diff line number Diff line
@@ -35,10 +35,13 @@
 * PASIDs are global address space identifiers that can be shared
 * between the GPU, an IOMMU and the driver. VMs on different devices
 * may use the same PASID if they share the same address
 * space. Therefore PASIDs are allocated using a global IDA. VMs are
 * looked up from the PASID per amdgpu_device.
 * space. Therefore PASIDs are allocated using IDR cyclic allocator
 * (similar to kernel PID allocation) which naturally delays reuse.
 * VMs are looked up from the PASID per amdgpu_device.
 */
static DEFINE_IDA(amdgpu_pasid_ida);

static DEFINE_IDR(amdgpu_pasid_idr);
static DEFINE_SPINLOCK(amdgpu_pasid_idr_lock);

/* Helper to free pasid from a fence callback */
struct amdgpu_pasid_cb {
@@ -50,8 +53,8 @@ struct amdgpu_pasid_cb {
 * amdgpu_pasid_alloc - Allocate a PASID
 * @bits: Maximum width of the PASID in bits, must be at least 1
 *
 * Allocates a PASID of the given width while keeping smaller PASIDs
 * available if possible.
 * Uses kernel's IDR cyclic allocator (same as PID allocation).
 * Allocates sequentially with automatic wrap-around.
 *
 * Returns a positive integer on success. Returns %-EINVAL if bits==0.
 * Returns %-ENOSPC if no PASID was available. Returns %-ENOMEM on
@@ -59,14 +62,15 @@ struct amdgpu_pasid_cb {
 */
int amdgpu_pasid_alloc(unsigned int bits)
{
	int pasid = -EINVAL;
	int pasid;

	for (bits = min(bits, 31U); bits > 0; bits--) {
		pasid = ida_alloc_range(&amdgpu_pasid_ida, 1U << (bits - 1),
					(1U << bits) - 1, GFP_KERNEL);
		if (pasid != -ENOSPC)
			break;
	}
	if (bits == 0)
		return -EINVAL;

	spin_lock(&amdgpu_pasid_idr_lock);
	pasid = idr_alloc_cyclic(&amdgpu_pasid_idr, NULL, 1,
				 1U << bits, GFP_KERNEL);
	spin_unlock(&amdgpu_pasid_idr_lock);

	if (pasid >= 0)
		trace_amdgpu_pasid_allocated(pasid);
@@ -81,7 +85,10 @@ int amdgpu_pasid_alloc(unsigned int bits)
void amdgpu_pasid_free(u32 pasid)
{
	trace_amdgpu_pasid_freed(pasid);
	ida_free(&amdgpu_pasid_ida, pasid);

	spin_lock(&amdgpu_pasid_idr_lock);
	idr_remove(&amdgpu_pasid_idr, pasid);
	spin_unlock(&amdgpu_pasid_idr_lock);
}

static void amdgpu_pasid_free_cb(struct dma_fence *fence,
@@ -616,3 +623,15 @@ void amdgpu_vmid_mgr_fini(struct amdgpu_device *adev)
		}
	}
}

/**
 * amdgpu_pasid_mgr_cleanup - cleanup PASID manager
 *
 * Cleanup the IDR allocator.
 */
void amdgpu_pasid_mgr_cleanup(void)
{
	spin_lock(&amdgpu_pasid_idr_lock);
	idr_destroy(&amdgpu_pasid_idr);
	spin_unlock(&amdgpu_pasid_idr_lock);
}
+1 −0
Original line number Diff line number Diff line
@@ -74,6 +74,7 @@ int amdgpu_pasid_alloc(unsigned int bits);
void amdgpu_pasid_free(u32 pasid);
void amdgpu_pasid_free_delayed(struct dma_resv *resv,
			       u32 pasid);
void amdgpu_pasid_mgr_cleanup(void);

bool amdgpu_vmid_had_gpu_reset(struct amdgpu_device *adev,
			       struct amdgpu_vmid *id);
+4 −3
Original line number Diff line number Diff line
@@ -2898,6 +2898,7 @@ void amdgpu_vm_manager_fini(struct amdgpu_device *adev)
	xa_destroy(&adev->vm_manager.pasids);

	amdgpu_vmid_mgr_fini(adev);
	amdgpu_pasid_mgr_cleanup();
}

/**
@@ -2973,14 +2974,14 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
	if (!root)
		return false;

	addr /= AMDGPU_GPU_PAGE_SIZE;

	if (is_compute_context && !svm_range_restore_pages(adev, pasid, vmid,
	    node_id, addr, ts, write_fault)) {
	    node_id, addr >> PAGE_SHIFT, ts, write_fault)) {
		amdgpu_bo_unref(&root);
		return true;
	}

	addr /= AMDGPU_GPU_PAGE_SIZE;

	r = amdgpu_bo_reserve(root, true);
	if (r)
		goto error_unref;
Loading