diff mbox series

drm/i915: move segment iterator to match current offset

Message ID quw77kz25yey6pnli7dabf2zuwhfycgil5aajhgmz5f3cxxawz@s4qvuuluu42m (mailing list archive)
State New, archived
Headers show
Series drm/i915: move segment iterator to match current offset | expand

Commit Message

Krzysztof Karas Oct. 8, 2024, 9:22 a.m. UTC
Commit 255fc1703e42 ("drm/i915/gem: Calculate object page offset for
partial memory mapping") introduced a new offset that affects
r.sgt.curr value. This field is used in remap_sg() function, in
set_pte_at() call and changing its value causes page table entry to
also be affected (see set_ptes() description).
Example:
 1) upon entering remap_sg() r.sgt.curr could have already been changed to
  a value equal to or greater than r.sgt.max,
 2) set_pte_at() uses r.sgt.curr to map a page entry from another segment
  to the current one,
 3) r->sgt pointer is moved to the next entry returned from __sg_iter()
  only once,
 3) the memory of the mismapped page might become unavailabe (accessing
  some addresses causes -EFAULT).

This patch moves current r->sgt pointer as many segments, as initial
r.sgt.curr is still larger than r.sgt.max.

Signed-off-by: Krzysztof Karas <krzysztof.karas@intel.com>
---
 drivers/gpu/drm/i915/i915_mm.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
diff mbox series

Patch

diff --git a/drivers/gpu/drm/i915/i915_mm.c b/drivers/gpu/drm/i915/i915_mm.c
index f5c97a620962..9a140840214b 100644
--- a/drivers/gpu/drm/i915/i915_mm.c
+++ b/drivers/gpu/drm/i915/i915_mm.c
@@ -51,10 +51,22 @@  static inline unsigned long sgt_pfn(const struct remap_pfn *r)
 static int remap_sg(pte_t *pte, unsigned long addr, void *data)
 {
 	struct remap_pfn *r = data;
+	unsigned int sgt_offset;
 
 	if (GEM_WARN_ON(!r->sgt.sgp))
 		return -EINVAL;
 
+	if (r->sgt.curr == r->sgt.max) {
+		r->sgt = __sgt_iter(__sg_next(r->sgt.sgp), use_dma(r->iobase));
+	} else if (r->sgt.curr > r->sgt.max) {
+		sgt_offset = r->sgt.curr;
+		while (sgt_offset >= r->sgt.max) {
+			sgt_offset -= r->sgt.max;
+			r->sgt = __sgt_iter(__sg_next(r->sgt.sgp), use_dma(r->iobase));
+		}
+		r->sgt.curr = sgt_offset;
+	}
+
 	/* Special PTE are not associated with any struct page */
 	set_pte_at(r->mm, addr, pte,
 		   pte_mkspecial(pfn_pte(sgt_pfn(r), r->prot)));