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
This commit is contained in:
riastradh 2024-01-19 22:24:38 +00:00
parent 0b4ab1ab69
commit aef93b36e3
1 changed files with 23 additions and 10 deletions

View File

@ -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 <sys/cdefs.h>
__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 <linux/errno.h>
#include <linux/mutex.h>
@ -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;