Module Name:    src
Committed By:   mrg
Date:           Thu Feb 20 09:07:39 UTC 2020

Modified Files:
        src/sys/external/bsd/drm2/include/drm: bus_dma_hacks.h

Log Message:
in bus_dmamap_load_pglist() try a 32-element array of
bus_dma_segment_t's before attempting to allocate.

this hopefully avoids hangs i've had in X since updating
from netbsd-8 to netbsd-9 that i've tracked down to this
function failing with ENOMEM.

XXX: maybe can avoid the alloc entirely by batching these
calls in 32 segments each.

XXX pullup-9


To generate a diff of this commit:
cvs rdiff -u -r1.19 -r1.20 \
    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/include/drm/bus_dma_hacks.h
diff -u src/sys/external/bsd/drm2/include/drm/bus_dma_hacks.h:1.19 src/sys/external/bsd/drm2/include/drm/bus_dma_hacks.h:1.20
--- src/sys/external/bsd/drm2/include/drm/bus_dma_hacks.h:1.19	Wed Jan 22 07:53:45 2020
+++ src/sys/external/bsd/drm2/include/drm/bus_dma_hacks.h	Thu Feb 20 09:07:39 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: bus_dma_hacks.h,v 1.19 2020/01/22 07:53:45 jmcneill Exp $	*/
+/*	$NetBSD: bus_dma_hacks.h,v 1.20 2020/02/20 09:07:39 mrg Exp $	*/
 
 /*-
  * Copyright (c) 2013 The NetBSD Foundation, Inc.
@@ -118,12 +118,15 @@ bus_dmatag_bounces_paddr(bus_dma_tag_t d
 #endif
 }
 
+#define MAX_STACK_SEGS 32	/* XXXMRG: 512 bytes on 16 byte seg platforms */
+
 static inline int
 bus_dmamap_load_pglist(bus_dma_tag_t tag, bus_dmamap_t map,
     struct pglist *pglist, bus_size_t size, int flags)
 {
 	km_flag_t kmflags;
 	bus_dma_segment_t *segs;
+	bus_dma_segment_t stacksegs[MAX_STACK_SEGS];
 	int nsegs, seg;
 	struct vm_page *page;
 	int error;
@@ -136,14 +139,23 @@ bus_dmamap_load_pglist(bus_dma_tag_t tag
 	}
 
 	KASSERT(nsegs <= (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((nsegs * sizeof(segs[0])), kmflags);
-	if (segs == NULL)
-		return ENOMEM;
+	if (nsegs > MAX_STACK_SEGS) {
+		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((nsegs * sizeof(segs[0])), kmflags);
+		if (segs == NULL)
+			return ENOMEM;
+	} else {
+		segs = stacksegs;
+	}
 
 	seg = 0;
 	TAILQ_FOREACH(page, pglist, pageq.queue) {
@@ -166,7 +178,10 @@ bus_dmamap_load_pglist(bus_dma_tag_t tag
 fail1: __unused
 	bus_dmamap_unload(tag, map);
 fail0:	KASSERT(error);
-out:	kmem_free(segs, (nsegs * sizeof(segs[0])));
+out:	if (segs != stacksegs) {
+		KASSERT(nsegs > MAX_STACK_SEGS);
+		kmem_free(segs, (nsegs * sizeof(segs[0])));
+	}
 	return error;
 }
 

Reply via email to