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