Module Name:    src
Committed By:   riastradh
Date:           Mon Aug 27 15:26:50 UTC 2018

Modified Files:
        src/sys/external/bsd/drm2/dist/drm: drm_prime.c
        src/sys/external/bsd/drm2/dist/include/drm: drmP.h
        src/sys/external/bsd/drm2/drm: drm_gem_cma_helper.c
        src/sys/external/bsd/drm2/include/drm: bus_dma_hacks.h

Log Message:
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


To generate a diff of this commit:
cvs rdiff -u -r1.4 -r1.5 src/sys/external/bsd/drm2/dist/drm/drm_prime.c
cvs rdiff -u -r1.28 -r1.29 src/sys/external/bsd/drm2/dist/include/drm/drmP.h
cvs rdiff -u -r1.3 -r1.4 src/sys/external/bsd/drm2/drm/drm_gem_cma_helper.c
cvs rdiff -u -r1.11 -r1.12 \
    src/sys/external/bsd/drm2/include/drm/bus_dma_hacks.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/external/bsd/drm2/dist/drm/drm_prime.c
diff -u src/sys/external/bsd/drm2/dist/drm/drm_prime.c:1.4 src/sys/external/bsd/drm2/dist/drm/drm_prime.c:1.5
--- src/sys/external/bsd/drm2/dist/drm/drm_prime.c:1.4	Mon Aug 27 15:26:00 2018
+++ src/sys/external/bsd/drm2/dist/drm/drm_prime.c	Mon Aug 27 15:26:50 2018
@@ -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 @@ __KERNEL_RCSID(0, "$NetBSD: drm_prime.c,
 
 #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 @@ sg_alloc_table_from_pages(struct sg_tabl
 	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 @@ sg_alloc_table_from_pglist(struct sg_tab
 	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 @@ sg_alloc_table_from_pglist(struct sg_tab
 }
 
 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 @@ static void
 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 @@ EXPORT_SYMBOL(drm_prime_pages_to_sg);
 #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 @@ drm_prime_bus_dmamem_to_sg(bus_dma_segme
 		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 @@ bus_size_t
 drm_prime_sg_size(struct sg_table *sg)
 {
 
-	return sg->sgt_size;
+	return sg->sgt_npgs << PAGE_SHIFT;
 }
 
 void
@@ -896,22 +889,43 @@ drm_prime_sg_free(struct sg_table *sg)
 }
 
 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;
+
+	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;
 
-	return -bus_dmamem_map(dmat, sgt->sgt_segs, sgt->sgt_nsegs,
-	    sgt->sgt_size, kvap, flags);
+out1:	kfree(segs);
+out0:	return ret;
 }
 
 #else  /* !__NetBSD__ */

Index: src/sys/external/bsd/drm2/dist/include/drm/drmP.h
diff -u src/sys/external/bsd/drm2/dist/include/drm/drmP.h:1.28 src/sys/external/bsd/drm2/dist/include/drm/drmP.h:1.29
--- src/sys/external/bsd/drm2/dist/include/drm/drmP.h:1.28	Mon Aug 27 15:26:00 2018
+++ src/sys/external/bsd/drm2/dist/include/drm/drmP.h	Mon Aug 27 15:26:50 2018
@@ -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 int drm_gem_prime_fd_to_handle(st
 extern void drm_gem_dmabuf_release(struct dma_buf *dma_buf);
 
 #ifdef __NetBSD__
-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_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 bus_size_t drm_prime_sg_size(struct sg_table *);
 extern void drm_prime_sg_free(struct sg_table *);
 #else

Index: src/sys/external/bsd/drm2/drm/drm_gem_cma_helper.c
diff -u src/sys/external/bsd/drm2/drm/drm_gem_cma_helper.c:1.3 src/sys/external/bsd/drm2/drm/drm_gem_cma_helper.c:1.4
--- src/sys/external/bsd/drm2/drm/drm_gem_cma_helper.c:1.3	Mon Aug 27 15:26:16 2018
+++ src/sys/external/bsd/drm2/drm/drm_gem_cma_helper.c	Mon Aug 27 15:26:50 2018
@@ -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 <[email protected]>
@@ -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 @@ drm_gem_cma_create(struct drm_device *dd
 	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);
+	}
 	if (error)
 		goto failed;
 	error = bus_dmamem_map(obj->dmat, obj->dmasegs, nsegs,
@@ -61,7 +67,8 @@ drm_gem_cma_create(struct drm_device *dd
 	if (error)
 		goto destroy;
 
-	memset(obj->vaddr, 0, obj->dmasize);
+	if (!sgt)
+		memset(obj->vaddr, 0, obj->dmasize);
 
 	drm_gem_private_object_init(ddev, &obj->base, size);
 
@@ -79,6 +86,13 @@ failed:
 	return NULL;
 }
 
+struct drm_gem_cma_object *
+drm_gem_cma_create(struct drm_device *ddev, size_t size)
+{
+
+	return drm_gem_cma_create_internal(ddev, size, NULL);
+}
+
 static void
 drm_gem_cma_obj_free(struct drm_gem_cma_object *obj)
 {
@@ -229,42 +243,19 @@ drm_gem_cma_prime_get_sg_table(struct dr
 {
 	struct drm_gem_cma_object *obj = to_drm_gem_cma_obj(gem_obj);
 
-	return drm_prime_bus_dmamem_to_sg(obj->dmasegs, 1);
+	return drm_prime_bus_dmamem_to_sg(obj->dmat, obj->dmasegs, 1);
 }
 
 struct drm_gem_object *
 drm_gem_cma_prime_import_sg_table(struct drm_device *ddev,
     struct dma_buf_attachment *attach, struct sg_table *sgt)
 {
+	size_t size = drm_prime_sg_size(sgt);
 	struct drm_gem_cma_object *obj;
-	int error;
-
-	obj = kmem_zalloc(sizeof(*obj), KM_SLEEP);
-	obj->dmat = ddev->dmat;
-	obj->dmasize = drm_prime_sg_size(sgt);
 
-	error = bus_dmamap_create(obj->dmat, obj->dmasize, 1, obj->dmasize, 0,
-	    BUS_DMA_WAITOK, &obj->dmamap);
-	if (error)
-		goto failed;
-	/* XXX errno Linux->NetBSD */
-	error = -drm_prime_bus_dmamap_load_sgt(obj->dmat, obj->dmamap, sgt);
-	if (error)
-		goto destroy;
-	error = -drm_prime_bus_dmamem_map(obj->dmat, sgt, &obj->vaddr,
-	    BUS_DMA_WAITOK | BUS_DMA_COHERENT);
-	if (error)
-		goto unload;
+	obj = drm_gem_cma_create_internal(ddev, size, sgt);
 
 	return &obj->base;
-
-unload:
-	bus_dmamap_unload(obj->dmat, obj->dmamap);
-destroy:
-	bus_dmamap_destroy(obj->dmat, obj->dmamap);
-failed:
-	kmem_free(obj, sizeof(*obj));
-	return ERR_PTR(-error);	/* XXX errno NetBSD->Linux */
 }
 
 void *

Index: src/sys/external/bsd/drm2/include/drm/bus_dma_hacks.h
diff -u src/sys/external/bsd/drm2/include/drm/bus_dma_hacks.h:1.11 src/sys/external/bsd/drm2/include/drm/bus_dma_hacks.h:1.12
--- src/sys/external/bsd/drm2/include/drm/bus_dma_hacks.h:1.11	Mon Aug 27 15:11:58 2018
+++ src/sys/external/bsd/drm2/include/drm/bus_dma_hacks.h	Mon Aug 27 15:26:50 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: bus_dma_hacks.h,v 1.11 2018/08/27 15:11:58 riastradh Exp $	*/
+/*	$NetBSD: bus_dma_hacks.h,v 1.12 2018/08/27 15:26:50 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2013 The NetBSD Foundation, Inc.
@@ -43,9 +43,11 @@
 #if defined(__i386__) || defined(__x86_64__)
 #  include <x86/bus_private.h>
 #  include <x86/machdep.h>
-#  define	PHYS_TO_BUS_MEM(dmat, paddr)	(paddr)
+#  define	PHYS_TO_BUS_MEM(dmat, paddr)	((bus_addr_t)(paddr))
+#  define	BUS_MEM_TO_PHYS(dmat, baddr)	((paddr_t)(baddr))
 #elif defined(__arm__) || defined(__aarch64__)
-#  define	PHYS_TO_BUS_MEM(dmat, paddr)	(paddr)
+#  define	PHYS_TO_BUS_MEM(dmat, paddr)	((bus_addr_t)(paddr))
+#  define	BUS_MEM_TO_PHYS(dmat, baddr)	((paddr_t)(baddr))
 #elif defined(__powerpc__)
 #else
 #  error DRM GEM/TTM need new MI bus_dma APIs!  Halp!
@@ -113,4 +115,102 @@ out:	kmem_free(segs, (nsegs * sizeof(seg
 	return error;
 }
 
+static inline int
+bus_dmamap_load_pgarray(bus_dma_tag_t tag, bus_dmamap_t map,
+    struct vm_page **pgs, unsigned npgs, bus_size_t size, int flags)
+{
+	km_flag_t kmflags;
+	bus_dma_segment_t *segs;
+	unsigned i;
+	int error;
+
+	KASSERT((int)npgs <= (SIZE_MAX / sizeof(segs[0])));
+	switch (flags & (BUS_DMA_WAITOK|BUS_DMA_NOWAIT)) {
+	case BUS_DMA_WAITOK:	kmflags = KM_SLEEP;	break;
+	case BUS_DMA_NOWAIT:	kmflags = KM_NOSLEEP;	break;
+	default:		panic("invalid flags: %d", flags);
+	}
+	segs = kmem_alloc((npgs * sizeof(segs[0])), kmflags);
+	if (segs == NULL)
+		return ENOMEM;
+
+	for (i = 0; i < npgs; i++) {
+		paddr_t paddr = VM_PAGE_TO_PHYS(pgs[i]);
+		bus_addr_t baddr = PHYS_TO_BUS_MEM(tag, paddr);
+
+		segs[i].ds_addr = baddr;
+		segs[i].ds_len = PAGE_SIZE;
+	}
+
+	error = bus_dmamap_load_raw(tag, map, segs, npgs, size, flags);
+	if (error)
+		goto fail0;
+
+	/* Success!  */
+	error = 0;
+	goto out;
+
+fail1: __unused
+	bus_dmamap_unload(tag, map);
+fail0:	KASSERT(error);
+out:	kmem_free(segs, (npgs * sizeof(segs[0])));
+	return error;
+}
+
+static inline int
+bus_dmamem_export_pages(bus_dma_tag_t dmat, const bus_dma_segment_t *segs,
+    int nsegs, struct vm_page **pgs, unsigned npgs)
+{
+	int seg;
+	unsigned i;
+
+	i = 0;
+	for (seg = 0; seg < nsegs; seg++) {
+		bus_addr_t baddr = segs[i].ds_addr;
+		bus_size_t len = segs[i].ds_len;
+
+		while (len >= PAGE_SIZE) {
+			paddr_t paddr = BUS_MEM_TO_PHYS(dmat, baddr);
+
+			KASSERT(i < npgs);
+			pgs[i++] = PHYS_TO_VM_PAGE(paddr);
+
+			baddr += PAGE_SIZE;
+			len -= PAGE_SIZE;
+		}
+		KASSERT(len == 0);
+	}
+	KASSERT(i == npgs);
+
+	return 0;
+}
+
+static inline int
+bus_dmamem_import_pages(bus_dma_tag_t dmat, bus_dma_segment_t *segs,
+    int nsegs, int *rsegs, struct vm_page *const *pgs, unsigned npgs)
+{
+	int seg;
+	unsigned i;
+
+	seg = 0;
+	for (i = 0; i < npgs; i++) {
+		paddr_t paddr = VM_PAGE_TO_PHYS(pgs[i]);
+		bus_addr_t baddr = PHYS_TO_BUS_MEM(dmat, paddr);
+
+		if (seg > 0 && segs[seg - 1].ds_addr + PAGE_SIZE == baddr) {
+			segs[seg - 1].ds_len += PAGE_SIZE;
+		} else {
+			KASSERT(seg < nsegs);
+			segs[seg].ds_addr = baddr;
+			segs[seg].ds_len = PAGE_SIZE;
+			seg++;
+			KASSERT(seg <= nsegs);
+		}
+	}
+	KASSERT(seg <= nsegs);
+	*rsegs = seg;
+
+	return 0;
+}
+
 #endif	/* _DRM_BUS_DMA_HACKS_H_ */

Reply via email to