Module Name: src Committed By: matt Date: Sat Jul 16 21:33:46 UTC 2016
Modified Files: src/sys/arch/mips/mips: bus_dma.c Log Message: When doing dmamap syncs, try to use KSEG0/XKPHYS address if possible. XXX once hard page coloring is supported XKPHYS could be used all the time. To generate a diff of this commit: cvs rdiff -u -r1.34 -r1.35 src/sys/arch/mips/mips/bus_dma.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/mips/mips/bus_dma.c diff -u src/sys/arch/mips/mips/bus_dma.c:1.34 src/sys/arch/mips/mips/bus_dma.c:1.35 --- src/sys/arch/mips/mips/bus_dma.c:1.34 Tue Feb 17 09:58:33 2015 +++ src/sys/arch/mips/mips/bus_dma.c Sat Jul 16 21:33:46 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: bus_dma.c,v 1.34 2015/02/17 09:58:33 macallan Exp $ */ +/* $NetBSD: bus_dma.c,v 1.35 2016/07/16 21:33:46 matt Exp $ */ /*- * Copyright (c) 1997, 1998, 2001 The NetBSD Foundation, Inc. @@ -32,7 +32,7 @@ #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ -__KERNEL_RCSID(0, "$NetBSD: bus_dma.c,v 1.34 2015/02/17 09:58:33 macallan Exp $"); +__KERNEL_RCSID(0, "$NetBSD: bus_dma.c,v 1.35 2016/07/16 21:33:46 matt Exp $"); #define _MIPS_BUS_DMA_PRIVATE @@ -106,18 +106,16 @@ _bus_dmamap_load_buffer(bus_dma_tag_t t, void *buf, bus_size_t buflen, struct vmspace *vm, int flags, int *segp, bool first) { - bus_size_t sgsize; paddr_t baddr, curaddr, lastaddr; vaddr_t vaddr = (vaddr_t)buf, lastvaddr; - int seg = *segp; - bus_dma_segment_t *ds = &map->dm_segs[seg]; + bus_dma_segment_t *ds = &map->dm_segs[*segp]; bus_dma_segment_t * const eds = &map->dm_segs[map->_dm_segcnt]; + const bus_addr_t bmask = ~(map->_dm_boundary - 1); const bool d_cache_coherent = (mips_options.mips_cpu_flags & CPU_MIPS_D_CACHE_COHERENT) != 0; lastaddr = ds->ds_addr + ds->ds_len; lastvaddr = ds->_ds_vaddr + ds->ds_len; - const bus_size_t bmask = ~(map->_dm_boundary - 1); while (buflen > 0) { /* @@ -146,7 +144,7 @@ _bus_dmamap_load_buffer(bus_dma_tag_t t, /* * Compute the segment size, and adjust counts. */ - sgsize = PAGE_SIZE - ((uintptr_t)vaddr & PGOFSET); + bus_size_t sgsize = PAGE_SIZE - ((uintptr_t)vaddr & PGOFSET); if (sgsize > buflen) { sgsize = buflen; } @@ -174,8 +172,12 @@ _bus_dmamap_load_buffer(bus_dma_tag_t t, ds->_ds_vaddr = vaddr; first = false; } else if (curaddr == lastaddr - && (d_cache_coherent || lastvaddr == vaddr) - && ds->ds_len + sgsize <= map->dm_maxsegsz + && (d_cache_coherent +#ifndef __mips_o32 + || !MIPS_CACHE_VIRTUAL_ALIAS +#endif + || vaddr == lastvaddr) + && (ds->ds_len + sgsize) <= map->dm_maxsegsz && (map->_dm_boundary == 0 || ((ds->ds_addr ^ curaddr) & bmask) == 0)) { ds->ds_len += sgsize; @@ -185,6 +187,25 @@ _bus_dmamap_load_buffer(bus_dma_tag_t t, ds->ds_addr = curaddr; ds->ds_len = sgsize; ds->_ds_vaddr = vaddr; + /* + * If this segment uses the correct color, try to see + * if we can use a direct-mapped VA for the segment. + */ + if (!mips_cache_badalias(curaddr, vaddr)) { +#ifdef __mips_o32 + if (MIPS_KSEG0_P(curaddr + sgsize - 1)) { + ds->_ds_vaddr = + MIPS_PHYS_TO_KSEG0(curaddr); + } +#else + /* + * All physical addresses can be accessed + * via XKPHYS. + */ + ds->_ds_vaddr = + MIPS_PHYS_TO_XKPHYS_CACHED(curaddr); +#endif + } } lastaddr = curaddr + sgsize; @@ -496,6 +517,7 @@ _bus_dmamap_load_mbuf(bus_dma_tag_t t, b #endif STAT_INCR(unloads); } + /* * Make sure that on error condition we return "no valid mappings." */ @@ -803,6 +825,7 @@ _bus_dmamap_sync(bus_dma_tag_t t, bus_dm || (ops & (BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE)) == 0) goto bounce_it; +#ifdef _mips_o32 /* * If the mapping belongs to the kernel, or it belongs * to the currently-running process (XXX actually, vmspace), @@ -812,6 +835,7 @@ _bus_dmamap_sync(bus_dma_tag_t t, bus_dm */ const bool useindex = (!VMSPACE_IS_KERNEL_P(map->_dm_vmspace) && map->_dm_vmspace != curproc->p_vmspace); +#endif bus_dma_segment_t *seg = map->dm_segs; bus_dma_segment_t * const lastseg = seg + map->dm_nsegs; @@ -827,7 +851,7 @@ _bus_dmamap_sync(bus_dma_tag_t t, bus_dm * Now at the first segment to sync; nail each segment until we * have exhausted the length. */ - vaddr_t vaddr = seg->_ds_vaddr + offset; + register_t vaddr = (intptr_t)seg->_ds_vaddr + offset; minlen = ulmin(len, seg->ds_len - offset); #ifdef BUS_DMA_DEBUG @@ -843,13 +867,15 @@ _bus_dmamap_sync(bus_dma_tag_t t, bus_dm * If we are forced to use Index ops, it's always a * Write-back,Invalidate, so just do one test. */ - if (__predict_false(useindex)) { +#ifdef mips_o32 + if (__predict_false(useindex || vaddr == 0)) { mips_dcache_wbinv_range_index(vaddr, minlen); #ifdef BUS_DMA_DEBUG printf("\n"); #endif continue; } +#endif switch (ops) { case BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE: @@ -858,10 +884,10 @@ _bus_dmamap_sync(bus_dma_tag_t t, bus_dm case BUS_DMASYNC_PREREAD: { struct mips_cache_info * const mci = &mips_cache_info; - vaddr_t start = vaddr; - vaddr_t end = vaddr + minlen; - vaddr_t preboundary, firstboundary, lastboundary; - vaddr_t mask = mci->mci_dcache_align_mask; + register_t start = vaddr; + register_t end = vaddr + minlen; + register_t preboundary, firstboundary, lastboundary; + register_t mask = mci->mci_dcache_align_mask; preboundary = start & ~mask; firstboundary = (start + mask) & ~mask;