Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/external/bsd/drm2 Rework drm prime guts.
details: https://anonhg.NetBSD.org/src/rev/b1449dcaac17
branches: trunk
changeset: 364877:b1449dcaac17
user: riastradh <riastradh%NetBSD.org@localhost>
date: Mon Aug 27 15:26:50 2018 +0000
description:
Rework drm prime guts.
- Our faux struct sg_table is now just an array of _pages_, not of
bus dma segments.
- We handle bus dma segments only in the presence of an adult bus dma
tag.
- All bus dma hacks are once again confined to bus_dma_hacks.h, and
more neatly organized:
. bus_dmamem_export_pages translates bus dma segs to vm_page array
. bus_dmamem_import_pages translates vm_page array to bus dma segs
diffstat:
sys/external/bsd/drm2/dist/drm/drm_prime.c | 130 ++++++++++++---------
sys/external/bsd/drm2/dist/include/drm/drmP.h | 8 +-
sys/external/bsd/drm2/drm/drm_gem_cma_helper.c | 57 ++++-----
sys/external/bsd/drm2/include/drm/bus_dma_hacks.h | 106 +++++++++++++++++-
4 files changed, 203 insertions(+), 98 deletions(-)
diffs (truncated from 500 to 300 lines):
diff -r f549ca562d73 -r b1449dcaac17 sys/external/bsd/drm2/dist/drm/drm_prime.c
--- a/sys/external/bsd/drm2/dist/drm/drm_prime.c Mon Aug 27 15:26:33 2018 +0000
+++ b/sys/external/bsd/drm2/dist/drm/drm_prime.c Mon Aug 27 15:26:50 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: drm_prime.c,v 1.4 2018/08/27 15:26:00 riastradh Exp $ */
+/* $NetBSD: drm_prime.c,v 1.5 2018/08/27 15:26:50 riastradh Exp $ */
/*
* Copyright © 2012 Red Hat
@@ -29,7 +29,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: drm_prime.c,v 1.4 2018/08/27 15:26:00 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: drm_prime.c,v 1.5 2018/08/27 15:26:50 riastradh Exp $");
#include <linux/export.h>
#include <linux/dma-buf.h>
@@ -40,22 +40,22 @@
#ifdef __NetBSD__
+#include <drm/bus_dma_hacks.h>
+
/*
- * We use struct sg_table just to pass around an array of
- * bus_dma_segment_t from one device to another in drm prime. Since
- * this is _not_ a complete implementation of Linux's sg table
- * abstraction (e.g., it does not remember DMA addresses and RAM pages
- * separately, and it doesn't support the nested chained iteration of
- * Linux scatterlists), we isolate it to this file and make all callers
- * go through a few extra subroutines (drm_prime_sg_size,
- * drm_prime_sg_free, &c.) to use it. Don't use this outside drm
- * prime!
+ * We use struct sg_table just to pass around an array of pages from
+ * one device to another in drm prime. Since this is _not_ a complete
+ * implementation of Linux's sg table abstraction (e.g., it does not
+ * remember DMA addresses and RAM pages separately, and it doesn't
+ * support the nested chained iteration of Linux scatterlists), we
+ * isolate it to this file and make all callers go through a few extra
+ * subroutines (drm_prime_sg_size, drm_prime_sg_free, &c.) to use it.
+ * Don't use this outside drm prime!
*/
struct sg_table {
- bus_dma_segment_t *sgt_segs;
- int sgt_nsegs;
- bus_size_t sgt_size;
+ struct vm_page **sgt_pgs;
+ unsigned sgt_npgs;
};
static int
@@ -67,22 +67,19 @@
KASSERT(offset == 0);
KASSERT(size == npages << PAGE_SHIFT);
- sgt->sgt_segs = kcalloc(npages, sizeof(sgt->sgt_segs[0]), gfp);
- if (sgt->sgt_segs == NULL)
+ sgt->sgt_pgs = kcalloc(npages, sizeof(sgt->sgt_pgs[0]), gfp);
+ if (sgt->sgt_pgs == NULL)
return -ENOMEM;
- sgt->sgt_nsegs = npages;
- sgt->sgt_size = size;
+ sgt->sgt_npgs = npages;
- for (i = 0; i < npages; i++) {
- sgt->sgt_segs[i].ds_addr = VM_PAGE_TO_PHYS(&pages[i]->p_vmp);
- sgt->sgt_segs[i].ds_len = PAGE_SIZE;
- }
+ for (i = 0; i < npages; i++)
+ sgt->sgt_pgs[i] = &pages[i]->p_vmp;
return 0;
}
static int
-sg_alloc_table_from_pglist(struct sg_table *sgt, struct pglist *pglist,
+sg_alloc_table_from_pglist(struct sg_table *sgt, const struct pglist *pglist,
unsigned npages, bus_size_t offset, bus_size_t size, gfp_t gfp)
{
struct vm_page *pg;
@@ -91,17 +88,15 @@
KASSERT(offset == 0);
KASSERT(size == npages << PAGE_SHIFT);
- sgt->sgt_segs = kcalloc(npages, sizeof(sgt->sgt_segs[0]), gfp);
- if (sgt->sgt_segs == NULL)
+ sgt->sgt_pgs = kcalloc(npages, sizeof(sgt->sgt_pgs[0]), gfp);
+ if (sgt->sgt_pgs == NULL)
return -ENOMEM;
- sgt->sgt_nsegs = npages;
- sgt->sgt_size = size;
+ sgt->sgt_npgs = npages;
i = 0;
TAILQ_FOREACH(pg, pglist, pageq.queue) {
KASSERT(i < npages);
- sgt->sgt_segs[i].ds_addr = VM_PAGE_TO_PHYS(pg);
- sgt->sgt_segs[i].ds_len = PAGE_SIZE;
+ sgt->sgt_pgs[i] = pg;
}
KASSERT(i == npages);
@@ -109,25 +104,22 @@
}
static int
-sg_alloc_table_from_bus_dmamem(struct sg_table *sgt, bus_dma_segment_t *segs,
- int nsegs, gfp_t gfp)
+sg_alloc_table_from_bus_dmamem(struct sg_table *sgt, bus_dma_tag_t dmat,
+ const bus_dma_segment_t *segs, int nsegs, gfp_t gfp)
{
- int seg;
+ int ret;
KASSERT(nsegs > 0);
- sgt->sgt_segs = kcalloc(nsegs, sizeof(sgt->sgt_segs[0]), gfp);
- if (sgt->sgt_segs == NULL)
+ sgt->sgt_pgs = kcalloc(nsegs, sizeof(sgt->sgt_pgs[0]), gfp);
+ if (sgt->sgt_pgs == NULL)
return -ENOMEM;
- sgt->sgt_nsegs = nsegs;
- sgt->sgt_size = 0;
+ sgt->sgt_npgs = nsegs;
- for (seg = 0; seg < nsegs; seg++) {
- sgt->sgt_segs[seg].ds_addr = segs[seg].ds_addr;
- sgt->sgt_segs[seg].ds_len = segs[seg].ds_len;
- KASSERT(segs[seg].ds_len <= __type_max(bus_size_t) -
- sgt->sgt_size);
- sgt->sgt_size += segs[seg].ds_len;
- }
+ /* XXX errno NetBSD->Linux */
+ ret = -bus_dmamem_export_pages(dmat, segs, nsegs, sgt->sgt_pgs,
+ sgt->sgt_npgs);
+ if (ret)
+ return ret;
return 0;
}
@@ -136,10 +128,9 @@
sg_free_table(struct sg_table *sgt)
{
- kfree(sgt->sgt_segs);
- sgt->sgt_segs = NULL;
- sgt->sgt_nsegs = 0;
- sgt->sgt_size = 0;
+ kfree(sgt->sgt_pgs);
+ sgt->sgt_pgs = NULL;
+ sgt->sgt_npgs = 0;
}
#endif /* __NetBSD__ */
@@ -835,7 +826,8 @@
#ifdef __NetBSD__
struct sg_table *
-drm_prime_bus_dmamem_to_sg(bus_dma_segment_t *segs, int nsegs)
+drm_prime_bus_dmamem_to_sg(bus_dma_tag_t dmat, const bus_dma_segment_t *segs,
+ int nsegs)
{
struct sg_table *sg;
int ret;
@@ -846,7 +838,8 @@
goto out;
}
- ret = sg_alloc_table_from_bus_dmamem(sg, segs, nsegs, GFP_KERNEL);
+ ret = sg_alloc_table_from_bus_dmamem(sg, dmat, segs, nsegs,
+ GFP_KERNEL);
if (ret)
goto out;
@@ -884,7 +877,7 @@
drm_prime_sg_size(struct sg_table *sg)
{
- return sg->sgt_size;
+ return sg->sgt_npgs << PAGE_SHIFT;
}
void
@@ -896,22 +889,43 @@
}
int
-drm_prime_bus_dmamap_load_sgt(bus_dma_tag_t dmat, bus_dmamap_t map,
- struct sg_table *sgt)
+drm_prime_sg_to_bus_dmamem(bus_dma_tag_t dmat, bus_dma_segment_t *segs,
+ int nsegs, int *rsegs, const struct sg_table *sgt)
{
/* XXX errno NetBSD->Linux */
- return -bus_dmamap_load_raw(dmat, map, sgt->sgt_segs, sgt->sgt_nsegs,
- sgt->sgt_size, BUS_DMA_NOWAIT);
+ return -bus_dmamem_import_pages(dmat, segs, nsegs, rsegs, sgt->sgt_pgs,
+ sgt->sgt_npgs);
}
int
-drm_prime_bus_dmamem_map(bus_dma_tag_t dmat, struct sg_table *sgt, void **kvap,
- int flags)
+drm_prime_bus_dmamap_load_sgt(bus_dma_tag_t dmat, bus_dmamap_t map,
+ struct sg_table *sgt)
{
+ bus_dma_segment_t *segs;
+ bus_size_t size = drm_prime_sg_size(sgt);
+ int nsegs = sgt->sgt_npgs;
+ int ret;
- return -bus_dmamem_map(dmat, sgt->sgt_segs, sgt->sgt_nsegs,
- sgt->sgt_size, kvap, flags);
+ segs = kcalloc(sgt->sgt_npgs, sizeof(segs[0]), GFP_KERNEL);
+ if (segs == NULL) {
+ ret = -ENOMEM;
+ goto out0;
+ }
+
+ ret = drm_prime_sg_to_bus_dmamem(dmat, segs, nsegs, &nsegs, sgt);
+ if (ret)
+ goto out1;
+ KASSERT(nsegs <= sgt->sgt_npgs);
+
+ /* XXX errno NetBSD->Linux */
+ ret = -bus_dmamap_load_raw(dmat, map, segs, nsegs, size,
+ BUS_DMA_NOWAIT);
+ if (ret)
+ goto out1;
+
+out1: kfree(segs);
+out0: return ret;
}
#else /* !__NetBSD__ */
diff -r f549ca562d73 -r b1449dcaac17 sys/external/bsd/drm2/dist/include/drm/drmP.h
--- a/sys/external/bsd/drm2/dist/include/drm/drmP.h Mon Aug 27 15:26:33 2018 +0000
+++ b/sys/external/bsd/drm2/dist/include/drm/drmP.h Mon Aug 27 15:26:50 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: drmP.h,v 1.28 2018/08/27 15:26:00 riastradh Exp $ */
+/* $NetBSD: drmP.h,v 1.29 2018/08/27 15:26:50 riastradh Exp $ */
/*
* Internal Header for the Direct Rendering Manager
@@ -1182,10 +1182,10 @@
extern void drm_gem_dmabuf_release(struct dma_buf *dma_buf);
#ifdef __NetBSD__
+extern struct sg_table *drm_prime_bus_dmamem_to_sg(bus_dma_tag_t, const bus_dma_segment_t *, int);
+extern struct sg_table *drm_prime_pglist_to_sg(struct pglist *, unsigned);
+extern int drm_prime_sg_to_bus_dmamem(bus_dma_tag_t, bus_dma_segment_t *, int, int *, const struct sg_table *);
extern int drm_prime_bus_dmamap_load_sgt(bus_dma_tag_t, bus_dmamap_t, struct sg_table *);
-extern int drm_prime_bus_dmamem_map(bus_dma_tag_t, struct sg_table *, void **, int);
-extern struct sg_table *drm_prime_bus_dmamem_to_sg(bus_dma_segment_t *, int);
-extern struct sg_table *drm_prime_pglist_to_sg(struct pglist *, unsigned);
extern bus_size_t drm_prime_sg_size(struct sg_table *);
extern void drm_prime_sg_free(struct sg_table *);
#else
diff -r f549ca562d73 -r b1449dcaac17 sys/external/bsd/drm2/drm/drm_gem_cma_helper.c
--- a/sys/external/bsd/drm2/drm/drm_gem_cma_helper.c Mon Aug 27 15:26:33 2018 +0000
+++ b/sys/external/bsd/drm2/drm/drm_gem_cma_helper.c Mon Aug 27 15:26:50 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: drm_gem_cma_helper.c,v 1.3 2018/08/27 15:26:16 riastradh Exp $ */
+/* $NetBSD: drm_gem_cma_helper.c,v 1.4 2018/08/27 15:26:50 riastradh Exp $ */
/*-
* Copyright (c) 2015-2017 Jared McNeill <jmcneill%invisible.ca@localhost>
@@ -27,15 +27,16 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: drm_gem_cma_helper.c,v 1.3 2018/08/27 15:26:16 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: drm_gem_cma_helper.c,v 1.4 2018/08/27 15:26:50 riastradh Exp $");
#include <drm/drmP.h>
#include <drm/drm_gem_cma_helper.h>
#include <uvm/uvm.h>
-struct drm_gem_cma_object *
-drm_gem_cma_create(struct drm_device *ddev, size_t size)
+static struct drm_gem_cma_object *
+drm_gem_cma_create_internal(struct drm_device *ddev, size_t size,
+ struct sg_table *sgt)
{
struct drm_gem_cma_object *obj;
int error, nsegs;
@@ -44,8 +45,13 @@
obj->dmat = ddev->bus_dmat;
obj->dmasize = size;
- error = bus_dmamem_alloc(obj->dmat, obj->dmasize, PAGE_SIZE, 0,
- obj->dmasegs, 1, &nsegs, BUS_DMA_WAITOK);
+ if (sgt) {
+ error = -drm_prime_sg_to_bus_dmamem(obj->dmat, obj->dmasegs, 1,
+ &nsegs, sgt);
+ } else {
+ error = bus_dmamem_alloc(obj->dmat, obj->dmasize, PAGE_SIZE, 0,
+ obj->dmasegs, 1, &nsegs, BUS_DMA_WAITOK);
Home |
Main Index |
Thread Index |
Old Index