Commit 9b043680 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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

Pull drm fixes from Dave Airlie:
 "Happy New Year, jetlagged fixes from me, still pretty quiet, xe is
  most of this, with i915/nouveau/imagination fixes and some shmem
  cleanups.

  shmem:
   - docs and MODULE_LICENSE fix

  xe:
   - Ensure svm device memory is idle before migration completes
   - Fix a SVM debug printout
   - Use READ_ONCE() / WRITE_ONCE() for g2h_fence

  i915:
   - Fix eb_lookup_vmas() failure path

  nouveau:
   - fix prepare_fb warnings

  imagination:
   - prevent export of protected objects"

* tag 'drm-fixes-2026-01-02' of https://gitlab.freedesktop.org/drm/kernel:
  drm/i915/gem: Zero-initialize the eb.vma array in i915_gem_do_execbuffer
  drm/xe/guc: READ/WRITE_ONCE g2h_fence->done
  drm/pagemap, drm/xe: Ensure that the devmem allocation is idle before use
  drm/xe/svm: Fix a debug printout
  drm/gem-shmem: Fix the MODULE_LICENSE() string
  drm/gem-shmem: Fix typos in documentation
  drm/nouveau/dispnv50: Don't call drm_atomic_get_crtc_state() in prepare_fb
  drm/imagination: Disallow exporting of PM/FW protected objects
parents e3a97ab1 7be19f93
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -96,7 +96,8 @@ static int __drm_gem_shmem_init(struct drm_device *dev, struct drm_gem_shmem_obj
/**
 * drm_gem_shmem_init - Initialize an allocated object.
 * @dev: DRM device
 * @obj: The allocated shmem GEM object.
 * @shmem: The allocated shmem GEM object.
 * @size: Buffer size in bytes
 *
 * Returns:
 * 0 on success, or a negative error code on failure.
@@ -895,4 +896,4 @@ EXPORT_SYMBOL_GPL(drm_gem_shmem_prime_import_no_map);

MODULE_DESCRIPTION("DRM SHMEM memory-management helpers");
MODULE_IMPORT_NS("DMA_BUF");
MODULE_LICENSE("GPL v2");
MODULE_LICENSE("GPL");
+13 −4
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@
 * Copyright © 2024-2025 Intel Corporation
 */

#include <linux/dma-fence.h>
#include <linux/dma-mapping.h>
#include <linux/migrate.h>
#include <linux/pagemap.h>
@@ -408,10 +409,14 @@ int drm_pagemap_migrate_to_devmem(struct drm_pagemap_devmem *devmem_allocation,
		drm_pagemap_get_devmem_page(page, zdd);
	}

	err = ops->copy_to_devmem(pages, pagemap_addr, npages);
	err = ops->copy_to_devmem(pages, pagemap_addr, npages,
				  devmem_allocation->pre_migrate_fence);
	if (err)
		goto err_finalize;

	dma_fence_put(devmem_allocation->pre_migrate_fence);
	devmem_allocation->pre_migrate_fence = NULL;

	/* Upon success bind devmem allocation to range and zdd */
	devmem_allocation->timeslice_expiration = get_jiffies_64() +
		msecs_to_jiffies(timeslice_ms);
@@ -596,7 +601,7 @@ int drm_pagemap_evict_to_ram(struct drm_pagemap_devmem *devmem_allocation)
	for (i = 0; i < npages; ++i)
		pages[i] = migrate_pfn_to_page(src[i]);

	err = ops->copy_to_ram(pages, pagemap_addr, npages);
	err = ops->copy_to_ram(pages, pagemap_addr, npages, NULL);
	if (err)
		goto err_finalize;

@@ -732,7 +737,7 @@ static int __drm_pagemap_migrate_to_ram(struct vm_area_struct *vas,
	for (i = 0; i < npages; ++i)
		pages[i] = migrate_pfn_to_page(migrate.src[i]);

	err = ops->copy_to_ram(pages, pagemap_addr, npages);
	err = ops->copy_to_ram(pages, pagemap_addr, npages, NULL);
	if (err)
		goto err_finalize;

@@ -813,11 +818,14 @@ EXPORT_SYMBOL_GPL(drm_pagemap_pagemap_ops_get);
 * @ops: Pointer to the operations structure for GPU SVM device memory
 * @dpagemap: The struct drm_pagemap we're allocating from.
 * @size: Size of device memory allocation
 * @pre_migrate_fence: Fence to wait for or pipeline behind before migration starts.
 * (May be NULL).
 */
void drm_pagemap_devmem_init(struct drm_pagemap_devmem *devmem_allocation,
			     struct device *dev, struct mm_struct *mm,
			     const struct drm_pagemap_devmem_ops *ops,
			     struct drm_pagemap *dpagemap, size_t size)
			     struct drm_pagemap *dpagemap, size_t size,
			     struct dma_fence *pre_migrate_fence)
{
	init_completion(&devmem_allocation->detached);
	devmem_allocation->dev = dev;
@@ -825,6 +833,7 @@ void drm_pagemap_devmem_init(struct drm_pagemap_devmem *devmem_allocation,
	devmem_allocation->ops = ops;
	devmem_allocation->dpagemap = dpagemap;
	devmem_allocation->size = size;
	devmem_allocation->pre_migrate_fence = pre_migrate_fence;
}
EXPORT_SYMBOL_GPL(drm_pagemap_devmem_init);

+17 −20
Original line number Diff line number Diff line
@@ -951,13 +951,13 @@ static int eb_lookup_vmas(struct i915_execbuffer *eb)
		vma = eb_lookup_vma(eb, eb->exec[i].handle);
		if (IS_ERR(vma)) {
			err = PTR_ERR(vma);
			goto err;
			return err;
		}

		err = eb_validate_vma(eb, &eb->exec[i], vma);
		if (unlikely(err)) {
			i915_vma_put(vma);
			goto err;
			return err;
		}

		err = eb_add_vma(eb, &current_batch, i, vma);
@@ -966,19 +966,8 @@ static int eb_lookup_vmas(struct i915_execbuffer *eb)

		if (i915_gem_object_is_userptr(vma->obj)) {
			err = i915_gem_object_userptr_submit_init(vma->obj);
			if (err) {
				if (i + 1 < eb->buffer_count) {
					/*
					 * Execbuffer code expects last vma entry to be NULL,
					 * since we already initialized this entry,
					 * set the next value to NULL or we mess up
					 * cleanup handling.
					 */
					eb->vma[i + 1].vma = NULL;
				}

			if (err)
				return err;
			}

			eb->vma[i].flags |= __EXEC_OBJECT_USERPTR_INIT;
			eb->args->flags |= __EXEC_USERPTR_USED;
@@ -986,10 +975,6 @@ static int eb_lookup_vmas(struct i915_execbuffer *eb)
	}

	return 0;

err:
	eb->vma[i].vma = NULL;
	return err;
}

static int eb_lock_vmas(struct i915_execbuffer *eb)
@@ -3375,7 +3360,8 @@ i915_gem_do_execbuffer(struct drm_device *dev,

	eb.exec = exec;
	eb.vma = (struct eb_vma *)(exec + args->buffer_count + 1);
	eb.vma[0].vma = NULL;
	memset(eb.vma, 0, (args->buffer_count + 1) * sizeof(struct eb_vma));

	eb.batch_pool = NULL;

	eb.invalid_flags = __EXEC_OBJECT_UNKNOWN_FLAGS;
@@ -3584,7 +3570,18 @@ i915_gem_execbuffer2_ioctl(struct drm_device *dev, void *data,
	if (err)
		return err;

	/* Allocate extra slots for use by the command parser */
	/*
	 * Allocate extra slots for use by the command parser.
	 *
	 * Note that this allocation handles two different arrays (the
	 * exec2_list array, and the eventual eb.vma array introduced in
	 * i915_gem_do_execbuffer()), that reside in virtually contiguous
	 * memory. Also note that the allocation intentionally doesn't fill the
	 * area with zeros, because the exec2_list part doesn't need to be, as
	 * it's immediately overwritten by user data a few lines below.
	 * However, the eb.vma part is explicitly zeroed later in
	 * i915_gem_do_execbuffer().
	 */
	exec2_list = kvmalloc_array(count + 2, eb_element_size(),
				    __GFP_NOWARN | GFP_KERNEL);
	if (exec2_list == NULL) {
+11 −0
Original line number Diff line number Diff line
@@ -28,6 +28,16 @@ static void pvr_gem_object_free(struct drm_gem_object *obj)
	drm_gem_shmem_object_free(obj);
}

static struct dma_buf *pvr_gem_export(struct drm_gem_object *obj, int flags)
{
	struct pvr_gem_object *pvr_obj = gem_to_pvr_gem(obj);

	if (pvr_obj->flags & DRM_PVR_BO_PM_FW_PROTECT)
		return ERR_PTR(-EPERM);

	return drm_gem_prime_export(obj, flags);
}

static int pvr_gem_mmap(struct drm_gem_object *gem_obj, struct vm_area_struct *vma)
{
	struct pvr_gem_object *pvr_obj = gem_to_pvr_gem(gem_obj);
@@ -42,6 +52,7 @@ static int pvr_gem_mmap(struct drm_gem_object *gem_obj, struct vm_area_struct *v
static const struct drm_gem_object_funcs pvr_gem_object_funcs = {
	.free = pvr_gem_object_free,
	.print_info = drm_gem_shmem_object_print_info,
	.export = pvr_gem_export,
	.pin = drm_gem_shmem_object_pin,
	.unpin = drm_gem_shmem_object_unpin,
	.get_sg_table = drm_gem_shmem_object_get_sg_table,
+13 −0
Original line number Diff line number Diff line
@@ -152,8 +152,21 @@ static inline struct nv50_head_atom *
nv50_head_atom_get(struct drm_atomic_state *state, struct drm_crtc *crtc)
{
	struct drm_crtc_state *statec = drm_atomic_get_crtc_state(state, crtc);

	if (IS_ERR(statec))
		return (void *)statec;

	return nv50_head_atom(statec);
}

static inline struct nv50_head_atom *
nv50_head_atom_get_new(struct drm_atomic_state *state, struct drm_crtc *crtc)
{
	struct drm_crtc_state *statec = drm_atomic_get_new_crtc_state(state, crtc);

	if (!statec)
		return NULL;

	return nv50_head_atom(statec);
}

Loading