Commit 6916d570 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'drm-fixes-2026-05-16' of https://gitlab.freedesktop.org/drm/kernel

Pull drm fixes from Dave Airlie:
 "Weekly fixes pull, small and all over fixes, mostly xe and amdgpu,
  with some ttm and a core fix for the handle change pain.

  core:
   - fix for the fix for the handle change race

  ttm:
   - avoid infinite loop in swap out
   - avoid infinite loop in BO shrinking
   - convert -EAGAIN from dmem_cgroup_try_charge to -ENOSPC

  bridge:
   - imx8qxp-pxl2dpi: avoid ERR_PTR with device_node cleanup

  i915:
   - Skip __i915_request_skip() for already signaled requests
   - Fix VSC dynamic range signaling for RGB formats [dp]

  xe:
   - Madvise fix around purgeability tracking
   - Restore engine mask for specific blitter style
   - Couple UAF fixes
   - Drop unused ggtt_balloon field

  amdgpu:
   - Userq fixes
   - DCN 3.2 fix
   - RAS fix
   - GC 12 fix

  gma500:
   - oaktrail_lvds: fix i2c handling

  loongson:
   - use managed cleanup for connector polling

  panfrost:
   - handle results from reservation locking correctly

  qaic:
   - check for integer overflows in mmap logic

  rocket:
   - handle results from reservation locking correctly"

* tag 'drm-fixes-2026-05-16' of https://gitlab.freedesktop.org/drm/kernel: (26 commits)
  drm: Replace old pointer to new idr
  drm/loongson: Use managed KMS polling
  drm/ttm: Fix ttm_bo_shrink() infinite LRU walk on backup failure
  drm/ttm: Convert -EAGAIN from dmem_cgroup_try_charge to -ENOSPC
  drm/gma500/oaktrail_lvds: fix i2c adapter leaks on init
  drm/gma500/oaktrail_lvds: fix hang on init failure
  drm/gma500/oaktrail_hdmi: fix i2c adapter leak on setup
  drm/xe: Drop unused ggtt_balloon field
  accel/qaic: Add overflow check to remap_pfn_range during mmap
  drm/i915/dp: Fix VSC dynamic range signaling for RGB formats
  drm/i915: skip __i915_request_skip() for already signaled requests
  drm/bridge: imx8qxp-pxl2dpi: avoid ERR_PTR with device_node cleanup
  drm/amdgpu/gfx_v12_0: set gfx.rs64_enable from PFP header on GFX12
  drm/amd/ras: Fix CPER ring debugfs read overflow
  drm/amd/display: Wrap DCN32 phantom-plane allocation in DC_RUN_WITH_PREEMPTION_ENABLED
  drm/amdgpu: fix userq hang detection and reset
  drm/amdgpu: remove almost all calls to amdgpu_userq_detect_and_reset_queues
  drm/amdgpu: rework amdgpu_userq_signal_ioctl v3
  drm/amdgpu: remove deadlocks from amdgpu_userq_pre_reset
  drm/xe/dma-buf: fix UAF with retry loop
  ...
parents 36343a8f dc366607
Loading
Loading
Loading
Loading
+21 −2
Original line number Diff line number Diff line
@@ -606,8 +606,11 @@ static const struct vm_operations_struct drm_vm_ops = {
static int qaic_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
{
	struct qaic_bo *bo = to_qaic_bo(obj);
	unsigned long remap_start;
	unsigned long offset = 0;
	unsigned long remap_end;
	struct scatterlist *sg;
	unsigned long length;
	int ret = 0;

	if (drm_gem_is_imported(obj))
@@ -615,11 +618,27 @@ static int qaic_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struc

	for (sg = bo->sgt->sgl; sg; sg = sg_next(sg)) {
		if (sg_page(sg)) {
			/* if sg is too large for the VMA, so truncate it to fit */
			if (check_add_overflow(vma->vm_start, offset, &remap_start))
				return -EINVAL;
			if (check_add_overflow(remap_start, sg->length, &remap_end))
				return -EINVAL;

			if (remap_end > vma->vm_end) {
				if (check_sub_overflow(vma->vm_end, remap_start, &length))
					return -EINVAL;
			} else {
				length = sg->length;
			}

			if (length == 0)
				goto out;

			ret = remap_pfn_range(vma, vma->vm_start + offset, page_to_pfn(sg_page(sg)),
					      sg->length, vma->vm_page_prot);
					      length, vma->vm_page_prot);
			if (ret)
				goto out;
			offset += sg->length;
			offset += length;
		}
	}

+2 −0
Original line number Diff line number Diff line
@@ -145,6 +145,8 @@ int rocket_ioctl_prep_bo(struct drm_device *dev, void *data, struct drm_file *fi
	ret = dma_resv_wait_timeout(gem_obj->resv, DMA_RESV_USAGE_WRITE, true, timeout);
	if (!ret)
		ret = timeout ? -ETIMEDOUT : -EBUSY;
	else if (ret > 0)
		ret = 0;

	shmem_obj = &to_rocket_bo(gem_obj)->base;

+21 −8
Original line number Diff line number Diff line
@@ -552,8 +552,9 @@ static ssize_t amdgpu_debugfs_ring_read(struct file *f, char __user *buf,
					size_t size, loff_t *pos)
{
	struct amdgpu_ring *ring = file_inode(f)->i_private;
	uint32_t value, result, early[3];
	u32 value, result, early[3] = { 0 };
	uint64_t p;
	u32 avail_dw, start_dw, read_dw;
	loff_t i;
	int r;

@@ -565,10 +566,10 @@ static ssize_t amdgpu_debugfs_ring_read(struct file *f, char __user *buf,

	result = 0;

	if (*pos < 12) {
	if (ring->funcs->type == AMDGPU_RING_TYPE_CPER)
		mutex_lock(&ring->adev->cper.ring_lock);

	if (*pos < 12) {
		early[0] = amdgpu_ring_get_rptr(ring) & ring->buf_mask;
		early[1] = amdgpu_ring_get_wptr(ring) & ring->buf_mask;
		early[2] = ring->wptr & ring->buf_mask;
@@ -600,13 +601,24 @@ static ssize_t amdgpu_debugfs_ring_read(struct file *f, char __user *buf,
			*pos += 4;
		}
	} else {
		early[0] = amdgpu_ring_get_rptr(ring) & ring->buf_mask;
		early[1] = amdgpu_ring_get_wptr(ring) & ring->buf_mask;

		p = early[0];
		if (early[0] <= early[1])
			size = (early[1] - early[0]);
			avail_dw = early[1] - early[0];
		else
			size = ring->ring_size - (early[0] - early[1]);
			avail_dw = ring->buf_mask + 1 - (early[0] - early[1]);

		while (size) {
		start_dw = (*pos > 12) ? ((*pos - 12) >> 2) : 0;
		if (start_dw >= avail_dw)
			goto out;

		p = (p + start_dw) & ring->ptr_mask;
		avail_dw -= start_dw;
		read_dw = min_t(u32, avail_dw, size >> 2);

		while (read_dw) {
			if (p == early[1])
				goto out;

@@ -619,9 +631,10 @@ static ssize_t amdgpu_debugfs_ring_read(struct file *f, char __user *buf,

			buf += 4;
			result += 4;
			size--;
			read_dw--;
			p++;
			p &= ring->ptr_mask;
			*pos += 4;
		}
	}

+54 −77
Original line number Diff line number Diff line
@@ -106,9 +106,6 @@ amdgpu_userq_detect_and_reset_queues(struct amdgpu_userq_mgr *uq_mgr)
	int r = 0;
	int i;

	/* Warning if current process mutex is not held */
	WARN_ON(!mutex_is_locked(&uq_mgr->userq_mutex));

	if (unlikely(adev->debug_disable_gpu_ring_reset)) {
		dev_err(adev->dev, "userq reset disabled by debug mask\n");
		return 0;
@@ -127,9 +124,11 @@ amdgpu_userq_detect_and_reset_queues(struct amdgpu_userq_mgr *uq_mgr)
	 */
	for (i = 0; i < num_queue_types; i++) {
		int ring_type = queue_types[i];
		const struct amdgpu_userq_funcs *funcs = adev->userq_funcs[ring_type];
		const struct amdgpu_userq_funcs *funcs =
			adev->userq_funcs[ring_type];

		if (!amdgpu_userq_is_reset_type_supported(adev, ring_type, AMDGPU_RESET_TYPE_PER_QUEUE))
		if (!amdgpu_userq_is_reset_type_supported(adev, ring_type,
							  AMDGPU_RESET_TYPE_PER_QUEUE))
				continue;

		if (atomic_read(&uq_mgr->userq_count[ring_type]) > 0 &&
@@ -150,38 +149,22 @@ amdgpu_userq_detect_and_reset_queues(struct amdgpu_userq_mgr *uq_mgr)

static void amdgpu_userq_hang_detect_work(struct work_struct *work)
{
	struct amdgpu_usermode_queue *queue = container_of(work,
							  struct amdgpu_usermode_queue,
	struct amdgpu_usermode_queue *queue =
		container_of(work, struct amdgpu_usermode_queue,
			     hang_detect_work.work);
	struct dma_fence *fence;
	struct amdgpu_userq_mgr *uq_mgr;

	if (!queue->userq_mgr)
		return;

	uq_mgr = queue->userq_mgr;
	fence = READ_ONCE(queue->hang_detect_fence);
	/* Fence already signaled – no action needed */
	if (!fence || dma_fence_is_signaled(fence))
		return;

	mutex_lock(&uq_mgr->userq_mutex);
	amdgpu_userq_detect_and_reset_queues(uq_mgr);
	mutex_unlock(&uq_mgr->userq_mutex);
	amdgpu_userq_detect_and_reset_queues(queue->userq_mgr);
}

/*
 * Start hang detection for a user queue fence. A delayed work will be scheduled
 * to check if the fence is still pending after the timeout period.
 * to reset the queues when the fence doesn't signal in time.
 */
void amdgpu_userq_start_hang_detect_work(struct amdgpu_usermode_queue *queue)
{
	struct amdgpu_device *adev;
	unsigned long timeout_ms;

	if (!queue || !queue->userq_mgr || !queue->userq_mgr->adev)
		return;

	adev = queue->userq_mgr->adev;
	/* Determine timeout based on queue type */
	switch (queue->queue_type) {
@@ -199,8 +182,6 @@ void amdgpu_userq_start_hang_detect_work(struct amdgpu_usermode_queue *queue)
		break;
	}

	/* Store the fence to monitor and schedule hang detection */
	WRITE_ONCE(queue->hang_detect_fence, queue->last_fence);
	schedule_delayed_work(&queue->hang_detect_work,
		     msecs_to_jiffies(timeout_ms));
}
@@ -210,18 +191,24 @@ void amdgpu_userq_process_fence_irq(struct amdgpu_device *adev, u32 doorbell)
	struct xarray *xa = &adev->userq_doorbell_xa;
	struct amdgpu_usermode_queue *queue;
	unsigned long flags;
	int r;

	xa_lock_irqsave(xa, flags);
	queue = xa_load(xa, doorbell);
	if (queue)
		amdgpu_userq_fence_driver_process(queue->fence_drv);
	xa_unlock_irqrestore(xa, flags);
}
	if (queue) {
		r = amdgpu_userq_fence_driver_process(queue->fence_drv);
		/*
		 * We are in interrupt context here, this *can't* wait for
		 * reset work to finish.
		 */
		if (r >= 0)
			cancel_delayed_work(&queue->hang_detect_work);

static void amdgpu_userq_init_hang_detect_work(struct amdgpu_usermode_queue *queue)
{
	INIT_DELAYED_WORK(&queue->hang_detect_work, amdgpu_userq_hang_detect_work);
	queue->hang_detect_fence = NULL;
		/* Restart the timer when there are still fences pending */
		if (r == 1)
			amdgpu_userq_start_hang_detect_work(queue);
	}
	xa_unlock_irqrestore(xa, flags);
}

static int amdgpu_userq_buffer_va_list_add(struct amdgpu_usermode_queue *queue,
@@ -345,23 +332,18 @@ static int amdgpu_userq_preempt_helper(struct amdgpu_usermode_queue *queue)
	struct amdgpu_device *adev = uq_mgr->adev;
	const struct amdgpu_userq_funcs *userq_funcs =
		adev->userq_funcs[queue->queue_type];
	bool found_hung_queue = false;
	int r = 0;
	int r;

	if (queue->state == AMDGPU_USERQ_STATE_MAPPED) {
		r = userq_funcs->preempt(queue);
		if (r) {
			queue->state = AMDGPU_USERQ_STATE_HUNG;
			found_hung_queue = true;
			return r;
		} else {
			queue->state = AMDGPU_USERQ_STATE_PREEMPTED;
		}
	}

	if (found_hung_queue)
		amdgpu_userq_detect_and_reset_queues(uq_mgr);

	return r;
	return 0;
}

static int amdgpu_userq_restore_helper(struct amdgpu_usermode_queue *queue)
@@ -390,24 +372,21 @@ static int amdgpu_userq_unmap_helper(struct amdgpu_usermode_queue *queue)
	struct amdgpu_device *adev = uq_mgr->adev;
	const struct amdgpu_userq_funcs *userq_funcs =
		adev->userq_funcs[queue->queue_type];
	bool found_hung_queue = false;
	int r = 0;
	int r;

	if ((queue->state == AMDGPU_USERQ_STATE_MAPPED) ||
	    (queue->state == AMDGPU_USERQ_STATE_PREEMPTED)) {

		r = userq_funcs->unmap(queue);
		if (r) {
			queue->state = AMDGPU_USERQ_STATE_HUNG;
			found_hung_queue = true;
			return r;
		} else {
			queue->state = AMDGPU_USERQ_STATE_UNMAPPED;
		}
	}

	if (found_hung_queue)
		amdgpu_userq_detect_and_reset_queues(uq_mgr);

	return r;
	return 0;
}

static int amdgpu_userq_map_helper(struct amdgpu_usermode_queue *queue)
@@ -416,19 +395,19 @@ static int amdgpu_userq_map_helper(struct amdgpu_usermode_queue *queue)
	struct amdgpu_device *adev = uq_mgr->adev;
	const struct amdgpu_userq_funcs *userq_funcs =
		adev->userq_funcs[queue->queue_type];
	int r = 0;
	int r;

	if (queue->state == AMDGPU_USERQ_STATE_UNMAPPED) {
		r = userq_funcs->map(queue);
		if (r) {
			queue->state = AMDGPU_USERQ_STATE_HUNG;
			amdgpu_userq_detect_and_reset_queues(uq_mgr);
			return r;
		} else {
			queue->state = AMDGPU_USERQ_STATE_MAPPED;
		}
	}

	return r;
	return 0;
}

static void amdgpu_userq_wait_for_last_fence(struct amdgpu_usermode_queue *queue)
@@ -648,13 +627,11 @@ amdgpu_userq_destroy(struct amdgpu_userq_mgr *uq_mgr, struct amdgpu_usermode_que
	amdgpu_bo_unreserve(vm->root.bo);

	mutex_lock(&uq_mgr->userq_mutex);
	queue->hang_detect_fence = NULL;
	amdgpu_userq_wait_for_last_fence(queue);

#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);
	atomic_dec(&uq_mgr->userq_count[queue->queue_type]);
	amdgpu_userq_cleanup(queue);
@@ -800,6 +777,7 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
	}

	queue->doorbell_index = index;
	mutex_init(&queue->fence_drv_lock);
	xa_init_flags(&queue->fence_drv_xa, XA_FLAGS_ALLOC);
	r = amdgpu_userq_fence_driver_alloc(adev, &queue->fence_drv);
	if (r) {
@@ -855,7 +833,8 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
	up_read(&adev->reset_domain->sem);

	amdgpu_debugfs_userq_init(filp, queue, qid);
	amdgpu_userq_init_hang_detect_work(queue);
	INIT_DELAYED_WORK(&queue->hang_detect_work,
			  amdgpu_userq_hang_detect_work);

	args->out.queue_id = qid;
	atomic_inc(&uq_mgr->userq_count[queue->queue_type]);
@@ -873,6 +852,7 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
	amdgpu_bo_reserve(fpriv->vm.root.bo, true);
	amdgpu_userq_buffer_vas_list_cleanup(adev, queue);
	amdgpu_bo_unreserve(fpriv->vm.root.bo);
	mutex_destroy(&queue->fence_drv_lock);
free_queue:
	kfree(queue);
err_pm_runtime:
@@ -1262,7 +1242,6 @@ amdgpu_userq_evict_all(struct amdgpu_userq_mgr *uq_mgr)
	unsigned long queue_id;
	int ret = 0, r;

	amdgpu_userq_detect_and_reset_queues(uq_mgr);
	/* Try to unmap all the queues in this process ctx */
	xa_for_each(&uq_mgr->userq_xa, queue_id, queue) {
		r = amdgpu_userq_preempt_helper(queue);
@@ -1270,9 +1249,11 @@ amdgpu_userq_evict_all(struct amdgpu_userq_mgr *uq_mgr)
			ret = r;
	}

	if (ret)
	if (ret) {
		drm_file_err(uq_mgr->file,
			     "Couldn't unmap all the queues, eviction failed ret=%d\n", ret);
		amdgpu_userq_detect_and_reset_queues(uq_mgr);
	}
	return ret;
}

@@ -1372,7 +1353,6 @@ int amdgpu_userq_suspend(struct amdgpu_device *adev)
		uqm = queue->userq_mgr;
		cancel_delayed_work_sync(&uqm->resume_work);
		guard(mutex)(&uqm->userq_mutex);
		amdgpu_userq_detect_and_reset_queues(uqm);
		if (adev->in_s0ix)
			r = amdgpu_userq_preempt_helper(queue);
		else
@@ -1431,7 +1411,6 @@ int amdgpu_userq_stop_sched_for_enforce_isolation(struct amdgpu_device *adev,
		if (((queue->queue_type == AMDGPU_HW_IP_GFX) ||
		     (queue->queue_type == AMDGPU_HW_IP_COMPUTE)) &&
		    (queue->xcp_id == idx)) {
			amdgpu_userq_detect_and_reset_queues(uqm);
			r = amdgpu_userq_preempt_helper(queue);
			if (r)
				ret = r;
@@ -1504,14 +1483,13 @@ void amdgpu_userq_pre_reset(struct amdgpu_device *adev)
{
	const struct amdgpu_userq_funcs *userq_funcs;
	struct amdgpu_usermode_queue *queue;
	struct amdgpu_userq_mgr *uqm;
	unsigned long queue_id;

	/* TODO: We probably need a new lock for the queue state */
	xa_for_each(&adev->userq_doorbell_xa, queue_id, queue) {
		uqm = queue->userq_mgr;
		cancel_delayed_work_sync(&uqm->resume_work);
		if (queue->state == AMDGPU_USERQ_STATE_MAPPED) {
			amdgpu_userq_wait_for_last_fence(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.
@@ -1522,7 +1500,6 @@ void amdgpu_userq_pre_reset(struct amdgpu_device *adev)
		amdgpu_userq_fence_driver_force_completion(queue);
	}
}
}

int amdgpu_userq_post_reset(struct amdgpu_device *adev, bool vram_lost)
{
+12 −1
Original line number Diff line number Diff line
@@ -66,6 +66,18 @@ struct amdgpu_usermode_queue {
	struct amdgpu_userq_obj	db_obj;
	struct amdgpu_userq_obj fw_obj;
	struct amdgpu_userq_obj wptr_obj;

	/**
	 * @fence_drv_lock: Protecting @fence_drv_xa.
	 */
	struct mutex		fence_drv_lock;

	/**
	 * @fence_drv_xa:
	 *
	 * References to the external fence drivers returned by wait_ioctl.
	 * Dropped on the next signaled dma_fence or queue destruction.
	 */
	struct xarray		fence_drv_xa;
	struct amdgpu_userq_fence_driver *fence_drv;
	struct dma_fence	*last_fence;
@@ -73,7 +85,6 @@ struct amdgpu_usermode_queue {
	int			priority;
	struct dentry		*debugfs_queue;
	struct delayed_work hang_detect_work;
	struct dma_fence *hang_detect_fence;
	struct kref		refcount;

	struct list_head	userq_va_list;
Loading