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;
}