From aef93b36e3df3d7bfab81c21f0270e1c6e694085 Mon Sep 17 00:00:00 2001 From: riastradh Date: Fri, 19 Jan 2024 22:24:38 +0000 Subject: [PATCH] i915_gem_stolen: Fill sg_pgs, with size/PAGE_SIZE entries. Use sg_alloc_table_from_bus_dmamem to do this. i915_gem_mman.c vm_fault_cpu and i915_gem_object_release_mmap_offset both rely on sg_pgs to be a page array, so providing a table with only one entry doesn't work (except by accident, if the object is page-sized anyway). And they rely on the sg_pgs entries to be initialized, which we weren't doing before, and which sg_alloc_table_from_bus_dmamem does for us. Related to PR kern/57833. XXX pullup-10 --- .../drm2/dist/drm/i915/gem/i915_gem_stolen.c | 33 +++++++++++++------ 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/sys/external/bsd/drm2/dist/drm/i915/gem/i915_gem_stolen.c b/sys/external/bsd/drm2/dist/drm/i915/gem/i915_gem_stolen.c index bb96d4e22848..4f06e3360989 100644 --- a/sys/external/bsd/drm2/dist/drm/i915/gem/i915_gem_stolen.c +++ b/sys/external/bsd/drm2/dist/drm/i915/gem/i915_gem_stolen.c @@ -1,4 +1,4 @@ -/* $NetBSD: i915_gem_stolen.c,v 1.6 2024/01/19 22:24:27 riastradh Exp $ */ +/* $NetBSD: i915_gem_stolen.c,v 1.7 2024/01/19 22:24:38 riastradh Exp $ */ /* * SPDX-License-Identifier: MIT @@ -7,7 +7,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: i915_gem_stolen.c,v 1.6 2024/01/19 22:24:27 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: i915_gem_stolen.c,v 1.7 2024/01/19 22:24:38 riastradh Exp $"); #include #include @@ -506,14 +506,13 @@ i915_pages_create_for_stolen(struct drm_device *dev, { struct drm_i915_private *i915 = to_i915(dev); struct sg_table *st; + struct scatterlist *sg; #ifdef __NetBSD__ bus_dma_tag_t dmat = i915->drm.dmat; bus_dma_segment_t *seg = NULL; int nseg = 0, i; bool loaded = false; int ret; -#else - struct scatterlist *sg; #endif GEM_BUG_ON(range_overflows(offset, size, resource_size(&i915->dsm))); @@ -527,11 +526,6 @@ i915_pages_create_for_stolen(struct drm_device *dev, if (st == NULL) return ERR_PTR(-ENOMEM); - if (sg_alloc_table(st, 1, GFP_KERNEL)) { - kfree(st); - return ERR_PTR(-ENOMEM); - } - #ifdef __NetBSD__ KASSERT((size % PAGE_SIZE) == 0); nseg = size / PAGE_SIZE; @@ -548,6 +542,17 @@ i915_pages_create_for_stolen(struct drm_device *dev, seg[i].ds_len = PAGE_SIZE; } + sg = NULL; + + ret = sg_alloc_table_from_bus_dmamem(st, dmat, seg, nseg, GFP_KERNEL); + if (ret) { + DRM_ERROR("failed to alloc sg table for stolen object: %d\n", + ret); + ret = -ENOMEM; + goto out; + } + sg = st->sgl; + /* XXX errno NetBSD->Linux */ ret = -bus_dmamap_create(dmat, size, nseg, PAGE_SIZE, 0, BUS_DMA_WAITOK, &st->sgl->sg_dmamap); @@ -573,11 +578,19 @@ out: kmem_free(seg, nseg * sizeof(seg[0])); if (ret) { if (loaded) bus_dmamap_unload(dmat, st->sgl->sg_dmamap); - sg_free_table(st); + if (sg && sg->sg_dmamap) + bus_dmamap_destroy(dmat, sg->sg_dmamap); + if (sg) + sg_free_table(st); kfree(st); return ERR_PTR(ret); } #else + if (sg_alloc_table(st, 1, GFP_KERNEL)) { + kfree(st); + return ERR_PTR(-ENOMEM); + } + sg = st->sgl; sg->offset = 0; sg->length = size;