@@ -61,7 +61,7 @@ __FBSDID("$FreeBSD$");
6161
6262#include <machine/atomic.h>
6363#include <machine/bus.h>
64- #include <machine/cpufunc .h>
64+ #include <machine/cpu-v6 .h>
6565#include <machine/md_var.h>
6666
6767#define MAX_BPAGES 64
@@ -110,8 +110,8 @@ struct bounce_page {
110110};
111111
112112struct sync_list {
113- vm_offset_t vaddr ; /* kva of bounce buffer */
114- bus_addr_t busaddr ; /* Physical address */
113+ vm_offset_t vaddr ; /* kva of client data */
114+ bus_addr_t busaddr ; /* client physical address */
115115 bus_size_t datacount ; /* client data count */
116116};
117117
@@ -625,7 +625,8 @@ bus_dma_tag_destroy(bus_dma_tag_t dmat)
625625 return (error );
626626}
627627
628- static int allocate_bz_and_pages (bus_dma_tag_t dmat , bus_dmamap_t mapp )
628+ static int
629+ allocate_bz_and_pages (bus_dma_tag_t dmat , bus_dmamap_t mapp )
629630{
630631 struct bounce_zone * bz ;
631632 int maxpages ;
@@ -1043,6 +1044,7 @@ _bus_dmamap_load_phys(bus_dma_tag_t dmat,
10431044{
10441045 bus_addr_t curaddr ;
10451046 bus_size_t sgsize ;
1047+ struct sync_list * sl ;
10461048 int error ;
10471049
10481050 if (segs == NULL )
@@ -1051,7 +1053,7 @@ _bus_dmamap_load_phys(bus_dma_tag_t dmat,
10511053 counter_u64_add (maploads_total , 1 );
10521054 counter_u64_add (maploads_physmem , 1 );
10531055
1054- if (might_bounce (dmat , map , buflen , buflen )) {
1056+ if (might_bounce (dmat , map , ( bus_addr_t ) buf , buflen )) {
10551057 _bus_dmamap_count_phys (dmat , map , buf , buflen , flags );
10561058 if (map -> pagesneeded != 0 ) {
10571059 counter_u64_add (maploads_bounced , 1 );
@@ -1069,6 +1071,18 @@ _bus_dmamap_load_phys(bus_dma_tag_t dmat,
10691071 sgsize = MIN (sgsize , PAGE_SIZE );
10701072 curaddr = add_bounce_page (dmat , map , 0 , curaddr ,
10711073 sgsize );
1074+ } else {
1075+ sl = & map -> slist [map -> sync_count - 1 ];
1076+ if (map -> sync_count == 0 ||
1077+ curaddr != sl -> busaddr + sl -> datacount ) {
1078+ if (++ map -> sync_count > dmat -> nsegments )
1079+ goto cleanup ;
1080+ sl ++ ;
1081+ sl -> vaddr = 0 ;
1082+ sl -> datacount = sgsize ;
1083+ sl -> busaddr = curaddr ;
1084+ } else
1085+ sl -> datacount += sgsize ;
10721086 }
10731087 sgsize = _bus_dmamap_addseg (dmat , map , curaddr , sgsize , segs ,
10741088 segp );
@@ -1078,6 +1092,7 @@ _bus_dmamap_load_phys(bus_dma_tag_t dmat,
10781092 buflen -= sgsize ;
10791093 }
10801094
1095+ cleanup :
10811096 /*
10821097 * Did we fit?
10831098 */
@@ -1171,9 +1186,7 @@ _bus_dmamap_load_buffer(bus_dma_tag_t dmat,
11711186 } else {
11721187 sl = & map -> slist [map -> sync_count - 1 ];
11731188 if (map -> sync_count == 0 ||
1174- #ifdef ARM_L2_PIPT
11751189 curaddr != sl -> busaddr + sl -> datacount ||
1176- #endif
11771190 vaddr != sl -> vaddr + sl -> datacount ) {
11781191 if (++ map -> sync_count > dmat -> nsegments )
11791192 goto cleanup ;
@@ -1251,58 +1264,21 @@ _bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map)
12511264 map -> flags &= ~DMAMAP_MBUF ;
12521265}
12531266
1254- #ifdef notyetbounceuser
1255- /* If busdma uses user pages, then the interrupt handler could
1256- * be use the kernel vm mapping. Both bounce pages and sync list
1257- * do not cross page boundaries.
1258- * Below is a rough sequence that a person would do to fix the
1259- * user page reference in the kernel vmspace. This would be
1260- * done in the dma post routine.
1261- */
1262- void
1263- _bus_dmamap_fix_user (vm_offset_t buf , bus_size_t len ,
1264- pmap_t pmap , int op )
1267+ static void
1268+ dma_dcache_ops (vm_paddr_t pa , vm_size_t size , int ops )
12651269{
1266- bus_size_t sgsize ;
1267- bus_addr_t curaddr ;
1268- vm_offset_t va ;
1269-
1270- /*
1271- * each synclist entry is contained within a single page.
1272- * this would be needed if BUS_DMASYNC_POSTxxxx was implemented
1273- */
1274- curaddr = pmap_extract (pmap , buf );
1275- va = pmap_dma_map (curaddr );
1276- switch (op ) {
1277- case SYNC_USER_INV :
1278- cpu_dcache_wb_range (va , sgsize );
1279- break ;
1280-
1281- case SYNC_USER_COPYTO :
1282- bcopy ((void * )va , (void * )bounce , sgsize );
1283- break ;
1284-
1285- case SYNC_USER_COPYFROM :
1286- bcopy ((void * ) bounce , (void * )va , sgsize );
1287- break ;
1288-
1289- default :
1290- break ;
1270+ uint32_t len , offset ;
1271+ vm_page_t m ;
1272+
1273+ offset = pa & PAGE_MASK ;
1274+ for ( ; size != 0 ; size -= len , pa += len , offset = 0 ) {
1275+ len = min (PAGE_SIZE - offset , size );
1276+ m = PHYS_TO_VM_PAGE (pa );
1277+ KASSERT (m != NULL , ("%s: vm_page_t is null for %#x" ,
1278+ __func__ , pa ));
1279+ pmap_dma_dcache_ops (pa , len , m -> md .pat_mode , ops );
12911280 }
1292-
1293- pmap_dma_unmap (va );
12941281}
1295- #endif
1296-
1297- #ifdef ARM_L2_PIPT
1298- #define l2cache_wb_range (va , pa , size ) cpu_l2cache_wb_range(pa, size)
1299- #define l2cache_wbinv_range (va , pa , size ) cpu_l2cache_wbinv_range(pa, size)
1300- #define l2cache_inv_range (va , pa , size ) cpu_l2cache_inv_range(pa, size)
1301- #else
1302- #define l2cache_wb_range (va , pa , size ) cpu_l2cache_wb_range(va, size)
1303- #define l2cache_wbinv_range (va , pa , size ) cpu_l2cache_wbinv_range(va, size)
1304- #define l2cache_inv_range (va , pa , size ) cpu_l2cache_inv_range(va, size)
1305- #endif
13061282
13071283void
13081284_bus_dmamap_sync (bus_dma_tag_t dmat , bus_dmamap_t map , bus_dmasync_op_t op )
@@ -1316,9 +1292,6 @@ _bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op)
13161292 * we're able to test direct userland dma, panic on a map mismatch.
13171293 */
13181294 if ((bpage = STAILQ_FIRST (& map -> bpages )) != NULL ) {
1319- if (!pmap_dmap_iscurrent (map -> pmap ))
1320- panic ("_bus_dmamap_sync: wrong user map for bounce sync." );
1321-
13221295 CTR4 (KTR_BUSDMA , "%s: tag %p tag flags 0x%x op 0x%x "
13231296 "performing bounce" , __func__ , dmat , dmat -> flags , op );
13241297
@@ -1328,19 +1301,17 @@ _bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op)
13281301 */
13291302 if (op & BUS_DMASYNC_PREWRITE ) {
13301303 while (bpage != NULL ) {
1331- if (bpage -> datavaddr != 0 )
1304+ if (bpage -> datavaddr != 0 &&
1305+ pmap_dmap_iscurrent (map -> pmap ))
13321306 bcopy ((void * )bpage -> datavaddr ,
13331307 (void * )bpage -> vaddr ,
13341308 bpage -> datacount );
13351309 else
13361310 physcopyout (bpage -> dataaddr ,
13371311 (void * )bpage -> vaddr ,
13381312 bpage -> datacount );
1339- cpu_dcache_wb_range ((vm_offset_t )bpage -> vaddr ,
1340- bpage -> datacount );
1341- l2cache_wb_range ((vm_offset_t )bpage -> vaddr ,
1342- (vm_offset_t )bpage -> busaddr ,
1343- bpage -> datacount );
1313+ dcache_wb_poc (bpage -> vaddr ,
1314+ (vm_paddr_t )bpage -> busaddr , bpage -> datacount );
13441315 bpage = STAILQ_NEXT (bpage , links );
13451316 }
13461317 dmat -> bounce_zone -> total_bounced ++ ;
@@ -1360,11 +1331,8 @@ _bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op)
13601331 if ((op & BUS_DMASYNC_PREREAD ) && !(op & BUS_DMASYNC_PREWRITE )) {
13611332 bpage = STAILQ_FIRST (& map -> bpages );
13621333 while (bpage != NULL ) {
1363- cpu_dcache_inv_range ((vm_offset_t )bpage -> vaddr ,
1364- bpage -> datacount );
1365- l2cache_inv_range ((vm_offset_t )bpage -> vaddr ,
1366- (vm_offset_t )bpage -> busaddr ,
1367- bpage -> datacount );
1334+ dcache_dma_preread (bpage -> vaddr ,
1335+ (vm_paddr_t )bpage -> busaddr , bpage -> datacount );
13681336 bpage = STAILQ_NEXT (bpage , links );
13691337 }
13701338 }
@@ -1380,23 +1348,10 @@ _bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op)
13801348 */
13811349 if (op & BUS_DMASYNC_POSTREAD ) {
13821350 while (bpage != NULL ) {
1383- vm_offset_t startv ;
1384- vm_paddr_t startp ;
1385- int len ;
1386-
1387- startv = bpage -> vaddr & ~ arm_dcache_align_mask ;
1388- startp = bpage -> busaddr & ~ arm_dcache_align_mask ;
1389- len = bpage -> datacount ;
1390-
1391- if (startv != bpage -> vaddr )
1392- len += bpage -> vaddr & arm_dcache_align_mask ;
1393- if (len & arm_dcache_align_mask )
1394- len = (len -
1395- (len & arm_dcache_align_mask )) +
1396- arm_dcache_align ;
1397- l2cache_inv_range (startv , startp , len );
1398- cpu_dcache_inv_range (startv , len );
1399- if (bpage -> datavaddr != 0 )
1351+ dcache_inv_poc (bpage -> vaddr ,
1352+ (vm_paddr_t )bpage -> busaddr , bpage -> datacount );
1353+ if (bpage -> datavaddr != 0 &&
1354+ pmap_dmap_iscurrent (map -> pmap ))
14001355 bcopy ((void * )bpage -> vaddr ,
14011356 (void * )bpage -> datavaddr ,
14021357 bpage -> datacount );
@@ -1434,9 +1389,6 @@ _bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op)
14341389 * outer-to-inner for POSTREAD invalidation is not a mistake.
14351390 */
14361391 if (map -> sync_count != 0 ) {
1437- if (!pmap_dmap_iscurrent (map -> pmap ))
1438- panic ("_bus_dmamap_sync: wrong user map for sync." );
1439-
14401392 sl = & map -> slist [0 ];
14411393 end = & map -> slist [map -> sync_count ];
14421394 CTR4 (KTR_BUSDMA , "%s: tag %p tag flags 0x%x op 0x%x "
@@ -1446,9 +1398,14 @@ _bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op)
14461398 case BUS_DMASYNC_PREWRITE :
14471399 case BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD :
14481400 while (sl != end ) {
1449- cpu_dcache_wb_range (sl -> vaddr , sl -> datacount );
1450- l2cache_wb_range (sl -> vaddr , sl -> busaddr ,
1451- sl -> datacount );
1401+ if (sl -> vaddr != 0 &&
1402+ pmap_dmap_iscurrent (map -> pmap ))
1403+ dcache_wb_poc (sl -> vaddr ,
1404+ (vm_paddr_t )sl -> busaddr ,
1405+ sl -> datacount );
1406+ else
1407+ dma_dcache_ops ((vm_paddr_t )sl -> busaddr ,
1408+ sl -> datacount , DDO_WB_POC );
14521409 sl ++ ;
14531410 }
14541411 break ;
@@ -1465,16 +1422,18 @@ _bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op)
14651422 * they are not aligned to a cacheline.
14661423 */
14671424 while (sl != end ) {
1468- if (sl -> vaddr & arm_dcache_align_mask ) {
1425+ if (sl -> busaddr & cpuinfo . dcache_line_mask ) {
14691426 KASSERT (map -> flags & DMAMAP_MBUF ,
14701427 ("unaligned buffer is not an mbuf" ));
1471- cpu_dcache_wb_range (sl -> vaddr , 1 );
1472- l2cache_wb_range (sl -> vaddr ,
1473- sl -> busaddr , 1 );
14741428 }
1475- cpu_dcache_inv_range (sl -> vaddr , sl -> datacount );
1476- l2cache_inv_range (sl -> vaddr , sl -> busaddr ,
1477- sl -> datacount );
1429+ if (sl -> vaddr != 0 &&
1430+ pmap_dmap_iscurrent (map -> pmap ))
1431+ dcache_dma_preread_safe (sl -> vaddr ,
1432+ (vm_paddr_t )sl -> busaddr ,
1433+ sl -> datacount );
1434+ else
1435+ dma_dcache_ops ((vm_paddr_t )sl -> busaddr ,
1436+ sl -> datacount , DDO_PREREAD_SAFE );
14781437 sl ++ ;
14791438 }
14801439 break ;
@@ -1485,9 +1444,14 @@ _bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op)
14851444 case BUS_DMASYNC_POSTREAD :
14861445 case BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE :
14871446 while (sl != end ) {
1488- l2cache_inv_range (sl -> vaddr , sl -> busaddr ,
1489- sl -> datacount );
1490- cpu_dcache_inv_range (sl -> vaddr , sl -> datacount );
1447+ if (sl -> vaddr != 0 &&
1448+ pmap_dmap_iscurrent (map -> pmap ))
1449+ dcache_inv_poc (sl -> vaddr ,
1450+ (vm_paddr_t )sl -> busaddr ,
1451+ sl -> datacount );
1452+ else
1453+ dma_dcache_ops ((vm_paddr_t )sl -> busaddr ,
1454+ sl -> datacount , DDO_INV_POC );
14911455 sl ++ ;
14921456 }
14931457 break ;
0 commit comments