Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/i915/gem: Calculate object page offset for partial memory mapping

To enable partial memory mapping of GPU virtual memory, it's
necessary to introduce an offset to the object's memory
(obj->mm.pages) scatterlist. This adjustment compensates for
instances when userspace mappings do not start from the beginning
of the object.

Based on a patch by Chris Wilson.

Signed-off-by: Andi Shyti <andi.shyti@linux.intel.com>
Cc: Chris Wilson <chris.p.wilson@linux.intel.com>
Cc: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Reviewed-by: Nirmoy Das <nirmoy.das@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240807100521.478266-3-andi.shyti@linux.intel.com

+16 -3
+3 -1
drivers/gpu/drm/i915/gem/i915_gem_mman.c
··· 252 252 struct vm_area_struct *area = vmf->vma; 253 253 struct i915_mmap_offset *mmo = area->vm_private_data; 254 254 struct drm_i915_gem_object *obj = mmo->obj; 255 + unsigned long obj_offset; 255 256 resource_size_t iomap; 256 257 int err; 257 258 ··· 274 273 iomap -= obj->mm.region->region.start; 275 274 } 276 275 276 + obj_offset = area->vm_pgoff - drm_vma_node_start(&mmo->vma_node); 277 277 /* PTEs are revoked in obj->ops->put_pages() */ 278 278 err = remap_io_sg(area, 279 279 area->vm_start, area->vm_end - area->vm_start, 280 - obj->mm.pages->sgl, iomap); 280 + obj->mm.pages->sgl, obj_offset, iomap); 281 281 282 282 if (area->vm_flags & VM_WRITE) { 283 283 GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj));
+11 -1
drivers/gpu/drm/i915/i915_mm.c
··· 122 122 * @addr: target user address to start at 123 123 * @size: size of map area 124 124 * @sgl: Start sg entry 125 + * @offset: offset from the start of the page 125 126 * @iobase: Use stored dma address offset by this address or pfn if -1 126 127 * 127 128 * Note: this is only safe if the mm semaphore is held when called. 128 129 */ 129 130 int remap_io_sg(struct vm_area_struct *vma, 130 131 unsigned long addr, unsigned long size, 131 - struct scatterlist *sgl, resource_size_t iobase) 132 + struct scatterlist *sgl, unsigned long offset, 133 + resource_size_t iobase) 132 134 { 133 135 struct remap_pfn r = { 134 136 .mm = vma->vm_mm, ··· 142 140 143 141 /* We rely on prevalidation of the io-mapping to skip track_pfn(). */ 144 142 GEM_BUG_ON((vma->vm_flags & EXPECTED_FLAGS) != EXPECTED_FLAGS); 143 + 144 + while (offset >= sg_dma_len(r.sgt.sgp) >> PAGE_SHIFT) { 145 + offset -= sg_dma_len(r.sgt.sgp) >> PAGE_SHIFT; 146 + r.sgt = __sgt_iter(__sg_next(r.sgt.sgp), use_dma(iobase)); 147 + if (!r.sgt.sgp) 148 + return -EINVAL; 149 + } 150 + r.sgt.curr = offset << PAGE_SHIFT; 145 151 146 152 if (!use_dma(iobase)) 147 153 flush_cache_range(vma, addr, size);
+2 -1
drivers/gpu/drm/i915/i915_mm.h
··· 30 30 31 31 int remap_io_sg(struct vm_area_struct *vma, 32 32 unsigned long addr, unsigned long size, 33 - struct scatterlist *sgl, resource_size_t iobase); 33 + struct scatterlist *sgl, unsigned long offset, 34 + resource_size_t iobase); 34 35 35 36 #endif /* __I915_MM_H__ */