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/6f0e43db754e
branches:  trunk
changeset: 835490:6f0e43db754e
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 a18129b24a34 -r 6f0e43db754e 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 a18129b24a34 -r 6f0e43db754e 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 a18129b24a34 -r 6f0e43db754e 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