Skip to content

Commit 6a1e8d1

Browse files
chleroyherbertx
authored andcommitted
crypto: talitos - making mapping helpers more generic
In preparation of IPSEC for SEC1, first step is to make the mapping helpers more generic so that they can also be used by AEAD functions. First, the functions are moved before IPSEC functions in talitos.c talitos_sg_unmap() and unmap_sg_talitos_ptr() are merged as they are quite similar, the second one handling the SEC1 case an calling the first one for SEC2 map_sg_in_talitos_ptr() and map_sg_out_talitos_ptr() are merged into talitos_sg_map() and enhenced to support offseted zones as used for AEAD. The actual mapping is now performed outside that helper. The DMA sync is also done outside to not make it several times. talitos_edesc_alloc() size calculation are fixed to also take into account AEAD specific parts also for SEC1 Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
1 parent 246a87c commit 6a1e8d1

File tree

1 file changed

+93
-137
lines changed

1 file changed

+93
-137
lines changed

drivers/crypto/talitos.c

Lines changed: 93 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -911,45 +911,28 @@ struct talitos_edesc {
911911
static 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

Comments
 (0)