@@ -911,45 +911,28 @@ struct talitos_edesc {
911911static void talitos_sg_unmap (struct device * dev ,
912912 struct talitos_edesc * edesc ,
913913 struct scatterlist * src ,
914- struct scatterlist * dst )
914+ struct scatterlist * dst ,
915+ unsigned int len , unsigned int offset )
915916{
917+ struct talitos_private * priv = dev_get_drvdata (dev );
918+ bool is_sec1 = has_ftr_sec1 (priv );
916919 unsigned int src_nents = edesc -> src_nents ? : 1 ;
917920 unsigned int dst_nents = edesc -> dst_nents ? : 1 ;
918921
922+ if (is_sec1 && dst && dst_nents > 1 ) {
923+ dma_sync_single_for_device (dev , edesc -> dma_link_tbl + offset ,
924+ len , DMA_FROM_DEVICE );
925+ sg_pcopy_from_buffer (dst , dst_nents , edesc -> buf + offset , len ,
926+ offset );
927+ }
919928 if (src != dst ) {
920- dma_unmap_sg (dev , src , src_nents , DMA_TO_DEVICE );
929+ if (src_nents == 1 || !is_sec1 )
930+ dma_unmap_sg (dev , src , src_nents , DMA_TO_DEVICE );
921931
922- if (dst ) {
932+ if (dst && ( dst_nents == 1 || ! is_sec1 ))
923933 dma_unmap_sg (dev , dst , dst_nents , DMA_FROM_DEVICE );
924- }
925- } else
934+ } else if (src_nents == 1 || !is_sec1 ) {
926935 dma_unmap_sg (dev , src , src_nents , DMA_BIDIRECTIONAL );
927- }
928-
929- static void unmap_sg_talitos_ptr (struct device * dev , struct scatterlist * src ,
930- struct scatterlist * dst , unsigned int len ,
931- struct talitos_edesc * edesc )
932- {
933- struct talitos_private * priv = dev_get_drvdata (dev );
934- bool is_sec1 = has_ftr_sec1 (priv );
935-
936- if (is_sec1 ) {
937- if (!edesc -> src_nents ) {
938- dma_unmap_sg (dev , src , 1 ,
939- dst != src ? DMA_TO_DEVICE
940- : DMA_BIDIRECTIONAL );
941- }
942- if (dst && edesc -> dst_nents ) {
943- dma_sync_single_for_device (dev ,
944- edesc -> dma_link_tbl + len ,
945- len , DMA_FROM_DEVICE );
946- sg_copy_from_buffer (dst , edesc -> dst_nents ? : 1 ,
947- edesc -> buf + len , len );
948- } else if (dst && dst != src ) {
949- dma_unmap_sg (dev , dst , 1 , DMA_FROM_DEVICE );
950- }
951- } else {
952- talitos_sg_unmap (dev , edesc , src , dst );
953936 }
954937}
955938
@@ -962,7 +945,8 @@ static void ipsec_esp_unmap(struct device *dev,
962945 unmap_single_talitos_ptr (dev , & edesc -> desc .ptr [2 ], DMA_TO_DEVICE );
963946 unmap_single_talitos_ptr (dev , & edesc -> desc .ptr [0 ], DMA_TO_DEVICE );
964947
965- talitos_sg_unmap (dev , edesc , areq -> src , areq -> dst );
948+ talitos_sg_unmap (dev , edesc , areq -> src , areq -> dst , areq -> cryptlen ,
949+ areq -> assoclen );
966950
967951 if (edesc -> dma_len )
968952 dma_unmap_single (dev , edesc -> dma_link_tbl , edesc -> dma_len ,
@@ -1110,99 +1094,37 @@ static inline int sg_to_link_tbl(struct scatterlist *sg, int sg_count,
11101094 link_tbl_ptr );
11111095}
11121096
1113- int map_sg_in_talitos_ptr (struct device * dev , struct scatterlist * src ,
1114- unsigned int len , struct talitos_edesc * edesc ,
1115- enum dma_data_direction dir , struct talitos_ptr * ptr )
1097+ int talitos_sg_map (struct device * dev , struct scatterlist * src ,
1098+ unsigned int len , struct talitos_edesc * edesc ,
1099+ struct talitos_ptr * ptr ,
1100+ int sg_count , unsigned int offset , int tbl_off )
11161101{
1117- int sg_count ;
11181102 struct talitos_private * priv = dev_get_drvdata (dev );
11191103 bool is_sec1 = has_ftr_sec1 (priv );
11201104
11211105 to_talitos_ptr_len (ptr , len , is_sec1 );
1106+ to_talitos_ptr_ext_set (ptr , 0 , is_sec1 );
11221107
1123- if (is_sec1 ) {
1124- sg_count = edesc -> src_nents ? : 1 ;
1125-
1126- if (sg_count == 1 ) {
1127- dma_map_sg (dev , src , 1 , dir );
1128- to_talitos_ptr (ptr , sg_dma_address (src ), is_sec1 );
1129- } else {
1130- sg_copy_to_buffer (src , sg_count , edesc -> buf , len );
1131- to_talitos_ptr (ptr , edesc -> dma_link_tbl , is_sec1 );
1132- dma_sync_single_for_device (dev , edesc -> dma_link_tbl ,
1133- len , DMA_TO_DEVICE );
1134- }
1135- } else {
1136- to_talitos_ptr_ext_set (ptr , 0 , is_sec1 );
1137-
1138- sg_count = dma_map_sg (dev , src , edesc -> src_nents ? : 1 , dir );
1139-
1140- if (sg_count == 1 ) {
1141- to_talitos_ptr (ptr , sg_dma_address (src ), is_sec1 );
1142- } else {
1143- sg_count = sg_to_link_tbl (src , sg_count , len ,
1144- & edesc -> link_tbl [0 ]);
1145- if (sg_count > 1 ) {
1146- to_talitos_ptr (ptr , edesc -> dma_link_tbl , 0 );
1147- to_talitos_ptr_ext_or (ptr , DESC_PTR_LNKTBL_JUMP ,
1148- 0 );
1149- dma_sync_single_for_device (dev ,
1150- edesc -> dma_link_tbl ,
1151- edesc -> dma_len ,
1152- DMA_BIDIRECTIONAL );
1153- } else {
1154- /* Only one segment now, so no link tbl needed*/
1155- to_talitos_ptr (ptr , sg_dma_address (src ),
1156- is_sec1 );
1157- }
1158- }
1108+ if (sg_count == 1 ) {
1109+ to_talitos_ptr (ptr , sg_dma_address (src ) + offset , is_sec1 );
1110+ return sg_count ;
11591111 }
1160- return sg_count ;
1161- }
1162-
1163- void map_sg_out_talitos_ptr (struct device * dev , struct scatterlist * dst ,
1164- unsigned int len , struct talitos_edesc * edesc ,
1165- enum dma_data_direction dir ,
1166- struct talitos_ptr * ptr , int sg_count )
1167- {
1168- struct talitos_private * priv = dev_get_drvdata (dev );
1169- bool is_sec1 = has_ftr_sec1 (priv );
1170-
1171- if (dir != DMA_NONE )
1172- sg_count = dma_map_sg (dev , dst , edesc -> dst_nents ? : 1 , dir );
1173-
1174- to_talitos_ptr_len (ptr , len , is_sec1 );
1175-
11761112 if (is_sec1 ) {
1177- if (sg_count == 1 ) {
1178- if (dir != DMA_NONE )
1179- dma_map_sg (dev , dst , 1 , dir );
1180- to_talitos_ptr (ptr , sg_dma_address (dst ), is_sec1 );
1181- } else {
1182- to_talitos_ptr (ptr , edesc -> dma_link_tbl + len , is_sec1 );
1183- dma_sync_single_for_device (dev ,
1184- edesc -> dma_link_tbl + len ,
1185- len , DMA_FROM_DEVICE );
1186- }
1187- } else {
1188- to_talitos_ptr_ext_set (ptr , 0 , is_sec1 );
1189-
1190- if (sg_count == 1 ) {
1191- to_talitos_ptr (ptr , sg_dma_address (dst ), is_sec1 );
1192- } else {
1193- struct talitos_ptr * link_tbl_ptr =
1194- & edesc -> link_tbl [edesc -> src_nents + 1 ];
1195-
1196- to_talitos_ptr (ptr , edesc -> dma_link_tbl +
1197- (edesc -> src_nents + 1 ) *
1198- sizeof (struct talitos_ptr ), 0 );
1199- to_talitos_ptr_ext_or (ptr , DESC_PTR_LNKTBL_JUMP , 0 );
1200- sg_to_link_tbl (dst , sg_count , len , link_tbl_ptr );
1201- dma_sync_single_for_device (dev , edesc -> dma_link_tbl ,
1202- edesc -> dma_len ,
1203- DMA_BIDIRECTIONAL );
1204- }
1113+ to_talitos_ptr (ptr , edesc -> dma_link_tbl + offset , is_sec1 );
1114+ return sg_count ;
12051115 }
1116+ sg_count = sg_to_link_tbl_offset (src , sg_count , offset , len ,
1117+ & edesc -> link_tbl [tbl_off ]);
1118+ if (sg_count == 1 ) {
1119+ /* Only one segment now, so no link tbl needed*/
1120+ copy_talitos_ptr (ptr , & edesc -> link_tbl [tbl_off ], is_sec1 );
1121+ return sg_count ;
1122+ }
1123+ to_talitos_ptr (ptr , edesc -> dma_link_tbl +
1124+ tbl_off * sizeof (struct talitos_ptr ), is_sec1 );
1125+ to_talitos_ptr_ext_or (ptr , DESC_PTR_LNKTBL_JUMP , is_sec1 );
1126+
1127+ return sg_count ;
12061128}
12071129
12081130/*
@@ -1363,7 +1285,7 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
13631285 bool encrypt )
13641286{
13651287 struct talitos_edesc * edesc ;
1366- int src_nents , dst_nents , alloc_len , dma_len ;
1288+ int src_nents , dst_nents , alloc_len , dma_len , src_len , dst_len ;
13671289 dma_addr_t iv_dma = 0 ;
13681290 gfp_t flags = cryptoflags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
13691291 GFP_ATOMIC ;
@@ -1381,26 +1303,27 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
13811303 iv_dma = dma_map_single (dev , iv , ivsize , DMA_TO_DEVICE );
13821304
13831305 if (!dst || dst == src ) {
1384- src_nents = sg_nents_for_len ( src ,
1385- assoclen + cryptlen + authsize );
1306+ src_len = assoclen + cryptlen + authsize ;
1307+ src_nents = sg_nents_for_len ( src , src_len );
13861308 if (src_nents < 0 ) {
13871309 dev_err (dev , "Invalid number of src SG.\n" );
13881310 err = ERR_PTR (- EINVAL );
13891311 goto error_sg ;
13901312 }
13911313 src_nents = (src_nents == 1 ) ? 0 : src_nents ;
13921314 dst_nents = dst ? src_nents : 0 ;
1315+ dst_len = 0 ;
13931316 } else { /* dst && dst != src*/
1394- src_nents = sg_nents_for_len ( src , assoclen + cryptlen +
1395- ( encrypt ? 0 : authsize ) );
1317+ src_len = assoclen + cryptlen + ( encrypt ? 0 : authsize );
1318+ src_nents = sg_nents_for_len ( src , src_len );
13961319 if (src_nents < 0 ) {
13971320 dev_err (dev , "Invalid number of src SG.\n" );
13981321 err = ERR_PTR (- EINVAL );
13991322 goto error_sg ;
14001323 }
14011324 src_nents = (src_nents == 1 ) ? 0 : src_nents ;
1402- dst_nents = sg_nents_for_len ( dst , assoclen + cryptlen +
1403- ( encrypt ? authsize : 0 ) );
1325+ dst_len = assoclen + cryptlen + ( encrypt ? authsize : 0 );
1326+ dst_nents = sg_nents_for_len ( dst , dst_len );
14041327 if (dst_nents < 0 ) {
14051328 dev_err (dev , "Invalid number of dst SG.\n" );
14061329 err = ERR_PTR (- EINVAL );
@@ -1417,8 +1340,8 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
14171340 alloc_len = sizeof (struct talitos_edesc );
14181341 if (src_nents || dst_nents ) {
14191342 if (is_sec1 )
1420- dma_len = (src_nents ? cryptlen : 0 ) +
1421- (dst_nents ? cryptlen : 0 );
1343+ dma_len = (src_nents ? src_len : 0 ) +
1344+ (dst_nents ? dst_len : 0 );
14221345 else
14231346 dma_len = (src_nents + dst_nents + 2 ) *
14241347 sizeof (struct talitos_ptr ) + authsize * 2 ;
@@ -1548,7 +1471,7 @@ static void common_nonsnoop_unmap(struct device *dev,
15481471{
15491472 unmap_single_talitos_ptr (dev , & edesc -> desc .ptr [5 ], DMA_FROM_DEVICE );
15501473
1551- unmap_sg_talitos_ptr (dev , areq -> src , areq -> dst , areq -> nbytes , edesc );
1474+ talitos_sg_unmap (dev , edesc , areq -> src , areq -> dst , areq -> nbytes , 0 );
15521475 unmap_single_talitos_ptr (dev , & edesc -> desc .ptr [2 ], DMA_TO_DEVICE );
15531476 unmap_single_talitos_ptr (dev , & edesc -> desc .ptr [1 ], DMA_TO_DEVICE );
15541477
@@ -1586,6 +1509,7 @@ static int common_nonsnoop(struct talitos_edesc *edesc,
15861509 unsigned int cryptlen = areq -> nbytes ;
15871510 unsigned int ivsize = crypto_ablkcipher_ivsize (cipher );
15881511 int sg_count , ret ;
1512+ bool sync_needed = false;
15891513 struct talitos_private * priv = dev_get_drvdata (dev );
15901514 bool is_sec1 = has_ftr_sec1 (priv );
15911515
@@ -1601,19 +1525,33 @@ static int common_nonsnoop(struct talitos_edesc *edesc,
16011525 map_single_talitos_ptr (dev , & desc -> ptr [2 ], ctx -> keylen ,
16021526 (char * )& ctx -> key , DMA_TO_DEVICE );
16031527
1528+ sg_count = edesc -> src_nents ?: 1 ;
1529+ if (is_sec1 && sg_count > 1 )
1530+ sg_copy_to_buffer (areq -> src , sg_count , edesc -> buf ,
1531+ cryptlen );
1532+ else
1533+ sg_count = dma_map_sg (dev , areq -> src , sg_count ,
1534+ (areq -> src == areq -> dst ) ?
1535+ DMA_BIDIRECTIONAL : DMA_TO_DEVICE );
16041536 /*
16051537 * cipher in
16061538 */
1607- sg_count = map_sg_in_talitos_ptr (dev , areq -> src , cryptlen , edesc ,
1608- ( areq -> src == areq -> dst ) ?
1609- DMA_BIDIRECTIONAL : DMA_TO_DEVICE ,
1610- & desc -> ptr [ 3 ]) ;
1539+ sg_count = talitos_sg_map (dev , areq -> src , cryptlen , edesc ,
1540+ & desc -> ptr [ 3 ], sg_count , 0 , 0 );
1541+ if ( sg_count > 1 )
1542+ sync_needed = true ;
16111543
16121544 /* cipher out */
1613- map_sg_out_talitos_ptr (dev , areq -> dst , cryptlen , edesc ,
1614- (areq -> src == areq -> dst ) ? DMA_NONE
1615- : DMA_FROM_DEVICE ,
1616- & desc -> ptr [4 ], sg_count );
1545+ if (areq -> src != areq -> dst ) {
1546+ sg_count = edesc -> dst_nents ? : 1 ;
1547+ if (!is_sec1 || sg_count == 1 )
1548+ dma_map_sg (dev , areq -> dst , sg_count , DMA_FROM_DEVICE );
1549+ }
1550+
1551+ ret = talitos_sg_map (dev , areq -> dst , cryptlen , edesc , & desc -> ptr [4 ],
1552+ sg_count , 0 , (edesc -> src_nents + 1 ));
1553+ if (ret > 1 )
1554+ sync_needed = true;
16171555
16181556 /* iv out */
16191557 map_single_talitos_ptr (dev , & desc -> ptr [5 ], ivsize , ctx -> iv ,
@@ -1622,6 +1560,10 @@ static int common_nonsnoop(struct talitos_edesc *edesc,
16221560 /* last DWORD empty */
16231561 desc -> ptr [6 ] = zero_entry ;
16241562
1563+ if (sync_needed )
1564+ dma_sync_single_for_device (dev , edesc -> dma_link_tbl ,
1565+ edesc -> dma_len , DMA_BIDIRECTIONAL );
1566+
16251567 ret = talitos_submit (dev , ctx -> ch , desc , callback , areq );
16261568 if (ret != - EINPROGRESS ) {
16271569 common_nonsnoop_unmap (dev , edesc , areq );
@@ -1685,7 +1627,7 @@ static void common_nonsnoop_hash_unmap(struct device *dev,
16851627
16861628 unmap_single_talitos_ptr (dev , & edesc -> desc .ptr [5 ], DMA_FROM_DEVICE );
16871629
1688- unmap_sg_talitos_ptr (dev , req_ctx -> psrc , NULL , 0 , edesc );
1630+ talitos_sg_unmap (dev , edesc , req_ctx -> psrc , NULL , 0 , 0 );
16891631
16901632 /* When using hashctx-in, must unmap it. */
16911633 if (from_talitos_ptr_len (& edesc -> desc .ptr [1 ], is_sec1 ))
@@ -1756,8 +1698,10 @@ static int common_nonsnoop_hash(struct talitos_edesc *edesc,
17561698 struct device * dev = ctx -> dev ;
17571699 struct talitos_desc * desc = & edesc -> desc ;
17581700 int ret ;
1701+ bool sync_needed = false;
17591702 struct talitos_private * priv = dev_get_drvdata (dev );
17601703 bool is_sec1 = has_ftr_sec1 (priv );
1704+ int sg_count ;
17611705
17621706 /* first DWORD empty */
17631707 desc -> ptr [0 ] = zero_entry ;
@@ -1782,11 +1726,19 @@ static int common_nonsnoop_hash(struct talitos_edesc *edesc,
17821726 else
17831727 desc -> ptr [2 ] = zero_entry ;
17841728
1729+ sg_count = edesc -> src_nents ?: 1 ;
1730+ if (is_sec1 && sg_count > 1 )
1731+ sg_copy_to_buffer (areq -> src , sg_count , edesc -> buf , length );
1732+ else
1733+ sg_count = dma_map_sg (dev , req_ctx -> psrc , sg_count ,
1734+ DMA_TO_DEVICE );
17851735 /*
17861736 * data in
17871737 */
1788- map_sg_in_talitos_ptr (dev , req_ctx -> psrc , length , edesc ,
1789- DMA_TO_DEVICE , & desc -> ptr [3 ]);
1738+ sg_count = talitos_sg_map (dev , req_ctx -> psrc , length , edesc ,
1739+ & desc -> ptr [3 ], sg_count , 0 , 0 );
1740+ if (sg_count > 1 )
1741+ sync_needed = true;
17901742
17911743 /* fifth DWORD empty */
17921744 desc -> ptr [4 ] = zero_entry ;
@@ -1807,6 +1759,10 @@ static int common_nonsnoop_hash(struct talitos_edesc *edesc,
18071759 if (is_sec1 && from_talitos_ptr_len (& desc -> ptr [3 ], true) == 0 )
18081760 talitos_handle_buggy_hash (ctx , edesc , & desc -> ptr [3 ]);
18091761
1762+ if (sync_needed )
1763+ dma_sync_single_for_device (dev , edesc -> dma_link_tbl ,
1764+ edesc -> dma_len , DMA_BIDIRECTIONAL );
1765+
18101766 ret = talitos_submit (dev , ctx -> ch , desc , callback , areq );
18111767 if (ret != - EINPROGRESS ) {
18121768 common_nonsnoop_hash_unmap (dev , edesc , areq );
0 commit comments