Changeset View
Changeset View
Standalone View
Standalone View
sys/mips/mips/busdma_machdep.c
Context not available. | |||||
#define BUS_DMA_COULD_BOUNCE BUS_DMA_BUS3 | #define BUS_DMA_COULD_BOUNCE BUS_DMA_BUS3 | ||||
#define BUS_DMA_MIN_ALLOC_COMP BUS_DMA_BUS4 | #define BUS_DMA_MIN_ALLOC_COMP BUS_DMA_BUS4 | ||||
/* | |||||
* On XBurst cores from Ingenic, cache-line writeback is local | |||||
* only, unless accompanied by invalidation. Invalidations force | |||||
* dirty line writeout and invalidation requests forwarded to | |||||
* other cores if other cores have the cache line dirty. | |||||
*/ | |||||
#if defined(SMP) && defined(CPU_XBURST) | |||||
#define BUS_DMA_FORCE_WBINV | |||||
#endif | |||||
struct bounce_zone; | struct bounce_zone; | ||||
struct bus_dma_tag { | struct bus_dma_tag { | ||||
Context not available. | |||||
/* | /* | ||||
* dcache invalidation operates on cache line aligned addresses | * dcache invalidation operates on cache line aligned addresses | ||||
* and could modify areas of memory that share the same cache line | * and could modify areas of memory that share the same cache line | ||||
* at the beginning and the ending of the buffer. In order to | * at the beginning and the ending of the buffer. In order to | ||||
* prevent a data loss we save these chunks in temporary buffer | * prevent a data loss we save these chunks in temporary buffer | ||||
* before invalidation and restore them afer it. | * before invalidation and restore them afer it. | ||||
* | * | ||||
Context not available. | |||||
case BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE: | case BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE: | ||||
case BUS_DMASYNC_POSTREAD: | case BUS_DMASYNC_POSTREAD: | ||||
/* | /* | ||||
* Save buffers that might be modified by invalidation | * Save buffers that might be modified by invalidation | ||||
*/ | */ | ||||
if (size_cl) | if (size_cl) | ||||
Context not available. | |||||
if (size_clend) | if (size_clend) | ||||
memcpy (tmp_clend, (void*)buf_clend, size_clend); | memcpy (tmp_clend, (void*)buf_clend, size_clend); | ||||
mips_dcache_inv_range(buf, len); | mips_dcache_inv_range(buf, len); | ||||
/* | /* | ||||
* Restore them | * Restore them | ||||
*/ | */ | ||||
if (size_cl) | if (size_cl) | ||||
memcpy ((void*)buf_cl, tmp_cl, size_cl); | memcpy ((void*)buf_cl, tmp_cl, size_cl); | ||||
if (size_clend) | if (size_clend) | ||||
memcpy ((void*)buf_clend, tmp_clend, size_clend); | memcpy ((void*)buf_clend, tmp_clend, size_clend); | ||||
/* | /* | ||||
* Copies above have brought corresponding memory | * Copies above have brought corresponding memory | ||||
* cache lines back into dirty state. Write them back | * cache lines back into dirty state. Write them back | ||||
* out and invalidate affected cache lines again if | * out and invalidate affected cache lines again if | ||||
Context not available. | |||||
break; | break; | ||||
case BUS_DMASYNC_PREREAD: | case BUS_DMASYNC_PREREAD: | ||||
/* | /* | ||||
* Save buffers that might be modified by invalidation | * Save buffers that might be modified by invalidation | ||||
*/ | */ | ||||
if (size_cl) | if (size_cl) | ||||
Context not available. | |||||
memcpy ((void *)buf_cl, tmp_cl, size_cl); | memcpy ((void *)buf_cl, tmp_cl, size_cl); | ||||
if (size_clend) | if (size_clend) | ||||
memcpy ((void *)buf_clend, tmp_clend, size_clend); | memcpy ((void *)buf_clend, tmp_clend, size_clend); | ||||
/* | /* | ||||
* Copies above have brought corresponding memory | * Copies above have brought corresponding memory | ||||
* cache lines back into dirty state. Write them back | * cache lines back into dirty state. Write them back | ||||
* out and invalidate affected cache lines again if | * out and invalidate affected cache lines again if | ||||
Context not available. | |||||
break; | break; | ||||
case BUS_DMASYNC_PREWRITE: | case BUS_DMASYNC_PREWRITE: | ||||
#ifdef BUS_DMA_FORCE_WBINV | |||||
mips_dcache_wbinv_range(buf, len); | |||||
#else | |||||
mips_dcache_wb_range(buf, len); | mips_dcache_wb_range(buf, len); | ||||
#endif | |||||
break; | break; | ||||
} | } | ||||
} | } | ||||
Context not available. | |||||
if (op & BUS_DMASYNC_PREWRITE) { | if (op & BUS_DMASYNC_PREWRITE) { | ||||
if (bpage->datavaddr != 0) | if (bpage->datavaddr != 0) | ||||
bcopy((void *)bpage->datavaddr, | bcopy((void *)bpage->datavaddr, | ||||
(void *)(bpage->vaddr_nocache != 0 ? | (void *)(bpage->vaddr_nocache != 0 ? | ||||
bpage->vaddr_nocache : | bpage->vaddr_nocache : | ||||
bpage->vaddr), | bpage->vaddr), | ||||
bpage->datacount); | bpage->datacount); | ||||
else | else | ||||
physcopyout(bpage->dataaddr, | physcopyout(bpage->dataaddr, | ||||
(void *)(bpage->vaddr_nocache != 0 ? | (void *)(bpage->vaddr_nocache != 0 ? | ||||
bpage->vaddr_nocache : | bpage->vaddr_nocache : | ||||
bpage->vaddr), | bpage->vaddr), | ||||
bpage->datacount); | bpage->datacount); | ||||
if (bpage->vaddr_nocache == 0) { | if (bpage->vaddr_nocache == 0) { | ||||
#ifdef BUS_DMA_FORCE_WBINV | |||||
mips_dcache_wbinv_range(bpage->vaddr, | |||||
bpage->datacount); | |||||
#else | |||||
mips_dcache_wb_range(bpage->vaddr, | mips_dcache_wb_range(bpage->vaddr, | ||||
bpage->datacount); | bpage->datacount); | ||||
#endif | |||||
} | } | ||||
dmat->bounce_zone->total_bounced++; | dmat->bounce_zone->total_bounced++; | ||||
} | } | ||||
Context not available. | |||||
bpage->datacount); | bpage->datacount); | ||||
} | } | ||||
if (bpage->datavaddr != 0) | if (bpage->datavaddr != 0) | ||||
bcopy((void *)(bpage->vaddr_nocache != 0 ? | bcopy((void *)(bpage->vaddr_nocache != 0 ? | ||||
bpage->vaddr_nocache : bpage->vaddr), | bpage->vaddr_nocache : bpage->vaddr), | ||||
(void *)bpage->datavaddr, bpage->datacount); | (void *)bpage->datavaddr, bpage->datacount); | ||||
else | else | ||||
physcopyin((void *)(bpage->vaddr_nocache != 0 ? | physcopyin((void *)(bpage->vaddr_nocache != 0 ? | ||||
bpage->vaddr_nocache : bpage->vaddr), | bpage->vaddr_nocache : bpage->vaddr), | ||||
bpage->dataaddr, bpage->datacount); | bpage->dataaddr, bpage->datacount); | ||||
dmat->bounce_zone->total_bounced++; | dmat->bounce_zone->total_bounced++; | ||||
Context not available. | |||||
{ | { | ||||
struct sync_list *sl, *end; | struct sync_list *sl, *end; | ||||
int aligned; | int aligned; | ||||
if (op == BUS_DMASYNC_POSTWRITE) | if (op == BUS_DMASYNC_POSTWRITE) | ||||
return; | return; | ||||
if (STAILQ_FIRST(&map->bpages)) | if (STAILQ_FIRST(&map->bpages)) | ||||
Context not available. | |||||
if (map->sync_count) { | if (map->sync_count) { | ||||
end = &map->slist[map->sync_count]; | end = &map->slist[map->sync_count]; | ||||
for (sl = &map->slist[0]; sl != end; sl++) | for (sl = &map->slist[0]; sl != end; sl++) | ||||
bus_dmamap_sync_buf(sl->vaddr, sl->datacount, op, | bus_dmamap_sync_buf(sl->vaddr, sl->datacount, op, | ||||
aligned); | aligned); | ||||
} | } | ||||
} | } | ||||
Context not available. |