diff options
author | Yuan Kang <Yuan.Kang@freescale.com> | 2012-06-22 20:48:45 -0400 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2012-06-27 02:42:05 -0400 |
commit | 4c1ec1f9301549db229bc6dce916f8a99d1f82d6 (patch) | |
tree | c97f112c51b6c4aea2cb52c2fe9e4b899cb86fec /drivers/crypto/caam | |
parent | 8009a383f28e853df1a1b08d405ccf67ba860fcc (diff) |
crypto: caam - refactor key_gen, sg
create separate files for split key generation and scatterlist functions.
Signed-off-by: Yuan Kang <Yuan.Kang@freescale.com>
Signed-off-by: Kim Phillips <kim.phillips@freescale.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'drivers/crypto/caam')
-rw-r--r-- | drivers/crypto/caam/Makefile | 2 | ||||
-rw-r--r-- | drivers/crypto/caam/caamalg.c | 197 | ||||
-rw-r--r-- | drivers/crypto/caam/desc.h | 10 | ||||
-rw-r--r-- | drivers/crypto/caam/key_gen.c | 122 | ||||
-rw-r--r-- | drivers/crypto/caam/key_gen.h | 17 | ||||
-rw-r--r-- | drivers/crypto/caam/sg_link_tbl.h | 84 |
6 files changed, 242 insertions, 190 deletions
diff --git a/drivers/crypto/caam/Makefile b/drivers/crypto/caam/Makefile index ef39011b4505..4447e5748c43 100644 --- a/drivers/crypto/caam/Makefile +++ b/drivers/crypto/caam/Makefile | |||
@@ -5,4 +5,4 @@ | |||
5 | obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM) += caam.o | 5 | obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM) += caam.o |
6 | obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API) += caamalg.o | 6 | obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API) += caamalg.o |
7 | 7 | ||
8 | caam-objs := ctrl.o jr.o error.o | 8 | caam-objs := ctrl.o jr.o error.o key_gen.o |
diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c index a4e266f928c2..ea0295d137a7 100644 --- a/drivers/crypto/caam/caamalg.c +++ b/drivers/crypto/caam/caamalg.c | |||
@@ -51,6 +51,8 @@ | |||
51 | #include "desc_constr.h" | 51 | #include "desc_constr.h" |
52 | #include "jr.h" | 52 | #include "jr.h" |
53 | #include "error.h" | 53 | #include "error.h" |
54 | #include "sg_link_tbl.h" | ||
55 | #include "key_gen.h" | ||
54 | 56 | ||
55 | /* | 57 | /* |
56 | * crypto alg | 58 | * crypto alg |
@@ -453,121 +455,12 @@ static int aead_setauthsize(struct crypto_aead *authenc, | |||
453 | return 0; | 455 | return 0; |
454 | } | 456 | } |
455 | 457 | ||
456 | struct split_key_result { | 458 | static u32 gen_split_aead_key(struct caam_ctx *ctx, const u8 *key_in, |
457 | struct completion completion; | 459 | u32 authkeylen) |
458 | int err; | ||
459 | }; | ||
460 | |||
461 | static void split_key_done(struct device *dev, u32 *desc, u32 err, | ||
462 | void *context) | ||
463 | { | 460 | { |
464 | struct split_key_result *res = context; | 461 | return gen_split_key(ctx->jrdev, ctx->key, ctx->split_key_len, |
465 | 462 | ctx->split_key_pad_len, key_in, authkeylen, | |
466 | #ifdef DEBUG | 463 | ctx->alg_op); |
467 | dev_err(dev, "%s %d: err 0x%x\n", __func__, __LINE__, err); | ||
468 | #endif | ||
469 | |||
470 | if (err) { | ||
471 | char tmp[CAAM_ERROR_STR_MAX]; | ||
472 | |||
473 | dev_err(dev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err)); | ||
474 | } | ||
475 | |||
476 | res->err = err; | ||
477 | |||
478 | complete(&res->completion); | ||
479 | } | ||
480 | |||
481 | /* | ||
482 | get a split ipad/opad key | ||
483 | |||
484 | Split key generation----------------------------------------------- | ||
485 | |||
486 | [00] 0xb0810008 jobdesc: stidx=1 share=never len=8 | ||
487 | [01] 0x04000014 key: class2->keyreg len=20 | ||
488 | @0xffe01000 | ||
489 | [03] 0x84410014 operation: cls2-op sha1 hmac init dec | ||
490 | [04] 0x24940000 fifold: class2 msgdata-last2 len=0 imm | ||
491 | [05] 0xa4000001 jump: class2 local all ->1 [06] | ||
492 | [06] 0x64260028 fifostr: class2 mdsplit-jdk len=40 | ||
493 | @0xffe04000 | ||
494 | */ | ||
495 | static u32 gen_split_key(struct caam_ctx *ctx, const u8 *key_in, u32 authkeylen) | ||
496 | { | ||
497 | struct device *jrdev = ctx->jrdev; | ||
498 | u32 *desc; | ||
499 | struct split_key_result result; | ||
500 | dma_addr_t dma_addr_in, dma_addr_out; | ||
501 | int ret = 0; | ||
502 | |||
503 | desc = kmalloc(CAAM_CMD_SZ * 6 + CAAM_PTR_SZ * 2, GFP_KERNEL | GFP_DMA); | ||
504 | |||
505 | init_job_desc(desc, 0); | ||
506 | |||
507 | dma_addr_in = dma_map_single(jrdev, (void *)key_in, authkeylen, | ||
508 | DMA_TO_DEVICE); | ||
509 | if (dma_mapping_error(jrdev, dma_addr_in)) { | ||
510 | dev_err(jrdev, "unable to map key input memory\n"); | ||
511 | kfree(desc); | ||
512 | return -ENOMEM; | ||
513 | } | ||
514 | append_key(desc, dma_addr_in, authkeylen, CLASS_2 | | ||
515 | KEY_DEST_CLASS_REG); | ||
516 | |||
517 | /* Sets MDHA up into an HMAC-INIT */ | ||
518 | append_operation(desc, ctx->alg_op | OP_ALG_DECRYPT | | ||
519 | OP_ALG_AS_INIT); | ||
520 | |||
521 | /* | ||
522 | * do a FIFO_LOAD of zero, this will trigger the internal key expansion | ||
523 | into both pads inside MDHA | ||
524 | */ | ||
525 | append_fifo_load_as_imm(desc, NULL, 0, LDST_CLASS_2_CCB | | ||
526 | FIFOLD_TYPE_MSG | FIFOLD_TYPE_LAST2); | ||
527 | |||
528 | /* | ||
529 | * FIFO_STORE with the explicit split-key content store | ||
530 | * (0x26 output type) | ||
531 | */ | ||
532 | dma_addr_out = dma_map_single(jrdev, ctx->key, ctx->split_key_pad_len, | ||
533 | DMA_FROM_DEVICE); | ||
534 | if (dma_mapping_error(jrdev, dma_addr_out)) { | ||
535 | dev_err(jrdev, "unable to map key output memory\n"); | ||
536 | kfree(desc); | ||
537 | return -ENOMEM; | ||
538 | } | ||
539 | append_fifo_store(desc, dma_addr_out, ctx->split_key_len, | ||
540 | LDST_CLASS_2_CCB | FIFOST_TYPE_SPLIT_KEK); | ||
541 | |||
542 | #ifdef DEBUG | ||
543 | print_hex_dump(KERN_ERR, "ctx.key@"xstr(__LINE__)": ", | ||
544 | DUMP_PREFIX_ADDRESS, 16, 4, key_in, authkeylen, 1); | ||
545 | print_hex_dump(KERN_ERR, "jobdesc@"xstr(__LINE__)": ", | ||
546 | DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1); | ||
547 | #endif | ||
548 | |||
549 | result.err = 0; | ||
550 | init_completion(&result.completion); | ||
551 | |||
552 | ret = caam_jr_enqueue(jrdev, desc, split_key_done, &result); | ||
553 | if (!ret) { | ||
554 | /* in progress */ | ||
555 | wait_for_completion_interruptible(&result.completion); | ||
556 | ret = result.err; | ||
557 | #ifdef DEBUG | ||
558 | print_hex_dump(KERN_ERR, "ctx.key@"xstr(__LINE__)": ", | ||
559 | DUMP_PREFIX_ADDRESS, 16, 4, ctx->key, | ||
560 | ctx->split_key_pad_len, 1); | ||
561 | #endif | ||
562 | } | ||
563 | |||
564 | dma_unmap_single(jrdev, dma_addr_out, ctx->split_key_pad_len, | ||
565 | DMA_FROM_DEVICE); | ||
566 | dma_unmap_single(jrdev, dma_addr_in, authkeylen, DMA_TO_DEVICE); | ||
567 | |||
568 | kfree(desc); | ||
569 | |||
570 | return ret; | ||
571 | } | 464 | } |
572 | 465 | ||
573 | static int aead_setkey(struct crypto_aead *aead, | 466 | static int aead_setkey(struct crypto_aead *aead, |
@@ -611,7 +504,7 @@ static int aead_setkey(struct crypto_aead *aead, | |||
611 | DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); | 504 | DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); |
612 | #endif | 505 | #endif |
613 | 506 | ||
614 | ret = gen_split_key(ctx, key, authkeylen); | 507 | ret = gen_split_aead_key(ctx, key, authkeylen); |
615 | if (ret) { | 508 | if (ret) { |
616 | goto badkey; | 509 | goto badkey; |
617 | } | 510 | } |
@@ -758,14 +651,6 @@ static int ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher, | |||
758 | return ret; | 651 | return ret; |
759 | } | 652 | } |
760 | 653 | ||
761 | struct link_tbl_entry { | ||
762 | u64 ptr; | ||
763 | u32 len; | ||
764 | u8 reserved; | ||
765 | u8 buf_pool_id; | ||
766 | u16 offset; | ||
767 | }; | ||
768 | |||
769 | /* | 654 | /* |
770 | * aead_edesc - s/w-extended aead descriptor | 655 | * aead_edesc - s/w-extended aead descriptor |
771 | * @assoc_nents: number of segments in associated data (SPI+Seq) scatterlist | 656 | * @assoc_nents: number of segments in associated data (SPI+Seq) scatterlist |
@@ -1027,50 +912,6 @@ static void ablkcipher_decrypt_done(struct device *jrdev, u32 *desc, u32 err, | |||
1027 | ablkcipher_request_complete(req, err); | 912 | ablkcipher_request_complete(req, err); |
1028 | } | 913 | } |
1029 | 914 | ||
1030 | static void sg_to_link_tbl_one(struct link_tbl_entry *link_tbl_ptr, | ||
1031 | dma_addr_t dma, u32 len, u32 offset) | ||
1032 | { | ||
1033 | link_tbl_ptr->ptr = dma; | ||
1034 | link_tbl_ptr->len = len; | ||
1035 | link_tbl_ptr->reserved = 0; | ||
1036 | link_tbl_ptr->buf_pool_id = 0; | ||
1037 | link_tbl_ptr->offset = offset; | ||
1038 | #ifdef DEBUG | ||
1039 | print_hex_dump(KERN_ERR, "link_tbl_ptr@"xstr(__LINE__)": ", | ||
1040 | DUMP_PREFIX_ADDRESS, 16, 4, link_tbl_ptr, | ||
1041 | sizeof(struct link_tbl_entry), 1); | ||
1042 | #endif | ||
1043 | } | ||
1044 | |||
1045 | /* | ||
1046 | * convert scatterlist to h/w link table format | ||
1047 | * but does not have final bit; instead, returns last entry | ||
1048 | */ | ||
1049 | static struct link_tbl_entry *sg_to_link_tbl(struct scatterlist *sg, | ||
1050 | int sg_count, struct link_tbl_entry | ||
1051 | *link_tbl_ptr, u32 offset) | ||
1052 | { | ||
1053 | while (sg_count) { | ||
1054 | sg_to_link_tbl_one(link_tbl_ptr, sg_dma_address(sg), | ||
1055 | sg_dma_len(sg), offset); | ||
1056 | link_tbl_ptr++; | ||
1057 | sg = sg_next(sg); | ||
1058 | sg_count--; | ||
1059 | } | ||
1060 | return link_tbl_ptr - 1; | ||
1061 | } | ||
1062 | |||
1063 | /* | ||
1064 | * convert scatterlist to h/w link table format | ||
1065 | * scatterlist must have been previously dma mapped | ||
1066 | */ | ||
1067 | static void sg_to_link_tbl_last(struct scatterlist *sg, int sg_count, | ||
1068 | struct link_tbl_entry *link_tbl_ptr, u32 offset) | ||
1069 | { | ||
1070 | link_tbl_ptr = sg_to_link_tbl(sg, sg_count, link_tbl_ptr, offset); | ||
1071 | link_tbl_ptr->len |= 0x40000000; | ||
1072 | } | ||
1073 | |||
1074 | /* | 915 | /* |
1075 | * Fill in aead job descriptor | 916 | * Fill in aead job descriptor |
1076 | */ | 917 | */ |
@@ -1272,28 +1113,6 @@ static void init_ablkcipher_job(u32 *sh_desc, dma_addr_t ptr, | |||
1272 | } | 1113 | } |
1273 | 1114 | ||
1274 | /* | 1115 | /* |
1275 | * derive number of elements in scatterlist | ||
1276 | */ | ||
1277 | static int sg_count(struct scatterlist *sg_list, int nbytes) | ||
1278 | { | ||
1279 | struct scatterlist *sg = sg_list; | ||
1280 | int sg_nents = 0; | ||
1281 | |||
1282 | while (nbytes > 0) { | ||
1283 | sg_nents++; | ||
1284 | nbytes -= sg->length; | ||
1285 | if (!sg_is_last(sg) && (sg + 1)->length == 0) | ||
1286 | BUG(); /* Not support chaining */ | ||
1287 | sg = scatterwalk_sg_next(sg); | ||
1288 | } | ||
1289 | |||
1290 | if (likely(sg_nents == 1)) | ||
1291 | return 0; | ||
1292 | |||
1293 | return sg_nents; | ||
1294 | } | ||
1295 | |||
1296 | /* | ||
1297 | * allocate and map the aead extended descriptor | 1116 | * allocate and map the aead extended descriptor |
1298 | */ | 1117 | */ |
1299 | static struct aead_edesc *aead_edesc_alloc(struct aead_request *req, | 1118 | static struct aead_edesc *aead_edesc_alloc(struct aead_request *req, |
diff --git a/drivers/crypto/caam/desc.h b/drivers/crypto/caam/desc.h index af25e76c5f7c..48c1927dbf21 100644 --- a/drivers/crypto/caam/desc.h +++ b/drivers/crypto/caam/desc.h | |||
@@ -8,6 +8,16 @@ | |||
8 | #ifndef DESC_H | 8 | #ifndef DESC_H |
9 | #define DESC_H | 9 | #define DESC_H |
10 | 10 | ||
11 | struct link_tbl_entry { | ||
12 | u64 ptr; | ||
13 | #define LINK_TBL_LEN_FIN 0x40000000 | ||
14 | #define LINK_TBL_LEN_EXT 0x80000000 | ||
15 | u32 len; | ||
16 | u8 reserved; | ||
17 | u8 buf_pool_id; | ||
18 | u16 offset; | ||
19 | }; | ||
20 | |||
11 | /* Max size of any CAAM descriptor in 32-bit words, inclusive of header */ | 21 | /* Max size of any CAAM descriptor in 32-bit words, inclusive of header */ |
12 | #define MAX_CAAM_DESCSIZE 64 | 22 | #define MAX_CAAM_DESCSIZE 64 |
13 | 23 | ||
diff --git a/drivers/crypto/caam/key_gen.c b/drivers/crypto/caam/key_gen.c new file mode 100644 index 000000000000..002888185f17 --- /dev/null +++ b/drivers/crypto/caam/key_gen.c | |||
@@ -0,0 +1,122 @@ | |||
1 | /* | ||
2 | * CAAM/SEC 4.x functions for handling key-generation jobs | ||
3 | * | ||
4 | * Copyright 2008-2011 Freescale Semiconductor, Inc. | ||
5 | * | ||
6 | */ | ||
7 | #include "compat.h" | ||
8 | #include "jr.h" | ||
9 | #include "error.h" | ||
10 | #include "desc_constr.h" | ||
11 | #include "key_gen.h" | ||
12 | |||
13 | void split_key_done(struct device *dev, u32 *desc, u32 err, | ||
14 | void *context) | ||
15 | { | ||
16 | struct split_key_result *res = context; | ||
17 | |||
18 | #ifdef DEBUG | ||
19 | dev_err(dev, "%s %d: err 0x%x\n", __func__, __LINE__, err); | ||
20 | #endif | ||
21 | |||
22 | if (err) { | ||
23 | char tmp[CAAM_ERROR_STR_MAX]; | ||
24 | |||
25 | dev_err(dev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err)); | ||
26 | } | ||
27 | |||
28 | res->err = err; | ||
29 | |||
30 | complete(&res->completion); | ||
31 | } | ||
32 | EXPORT_SYMBOL(split_key_done); | ||
33 | /* | ||
34 | get a split ipad/opad key | ||
35 | |||
36 | Split key generation----------------------------------------------- | ||
37 | |||
38 | [00] 0xb0810008 jobdesc: stidx=1 share=never len=8 | ||
39 | [01] 0x04000014 key: class2->keyreg len=20 | ||
40 | @0xffe01000 | ||
41 | [03] 0x84410014 operation: cls2-op sha1 hmac init dec | ||
42 | [04] 0x24940000 fifold: class2 msgdata-last2 len=0 imm | ||
43 | [05] 0xa4000001 jump: class2 local all ->1 [06] | ||
44 | [06] 0x64260028 fifostr: class2 mdsplit-jdk len=40 | ||
45 | @0xffe04000 | ||
46 | */ | ||
47 | u32 gen_split_key(struct device *jrdev, u8 *key_out, int split_key_len, | ||
48 | int split_key_pad_len, const u8 *key_in, u32 keylen, | ||
49 | u32 alg_op) | ||
50 | { | ||
51 | u32 *desc; | ||
52 | struct split_key_result result; | ||
53 | dma_addr_t dma_addr_in, dma_addr_out; | ||
54 | int ret = 0; | ||
55 | |||
56 | desc = kmalloc(CAAM_CMD_SZ * 6 + CAAM_PTR_SZ * 2, GFP_KERNEL | GFP_DMA); | ||
57 | |||
58 | init_job_desc(desc, 0); | ||
59 | |||
60 | dma_addr_in = dma_map_single(jrdev, (void *)key_in, keylen, | ||
61 | DMA_TO_DEVICE); | ||
62 | if (dma_mapping_error(jrdev, dma_addr_in)) { | ||
63 | dev_err(jrdev, "unable to map key input memory\n"); | ||
64 | kfree(desc); | ||
65 | return -ENOMEM; | ||
66 | } | ||
67 | append_key(desc, dma_addr_in, keylen, CLASS_2 | KEY_DEST_CLASS_REG); | ||
68 | |||
69 | /* Sets MDHA up into an HMAC-INIT */ | ||
70 | append_operation(desc, alg_op | OP_ALG_DECRYPT | OP_ALG_AS_INIT); | ||
71 | |||
72 | /* | ||
73 | * do a FIFO_LOAD of zero, this will trigger the internal key expansion | ||
74 | * into both pads inside MDHA | ||
75 | */ | ||
76 | append_fifo_load_as_imm(desc, NULL, 0, LDST_CLASS_2_CCB | | ||
77 | FIFOLD_TYPE_MSG | FIFOLD_TYPE_LAST2); | ||
78 | |||
79 | /* | ||
80 | * FIFO_STORE with the explicit split-key content store | ||
81 | * (0x26 output type) | ||
82 | */ | ||
83 | dma_addr_out = dma_map_single(jrdev, key_out, split_key_pad_len, | ||
84 | DMA_FROM_DEVICE); | ||
85 | if (dma_mapping_error(jrdev, dma_addr_out)) { | ||
86 | dev_err(jrdev, "unable to map key output memory\n"); | ||
87 | kfree(desc); | ||
88 | return -ENOMEM; | ||
89 | } | ||
90 | append_fifo_store(desc, dma_addr_out, split_key_len, | ||
91 | LDST_CLASS_2_CCB | FIFOST_TYPE_SPLIT_KEK); | ||
92 | |||
93 | #ifdef DEBUG | ||
94 | print_hex_dump(KERN_ERR, "ctx.key@"xstr(__LINE__)": ", | ||
95 | DUMP_PREFIX_ADDRESS, 16, 4, key_in, keylen, 1); | ||
96 | print_hex_dump(KERN_ERR, "jobdesc@"xstr(__LINE__)": ", | ||
97 | DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1); | ||
98 | #endif | ||
99 | |||
100 | result.err = 0; | ||
101 | init_completion(&result.completion); | ||
102 | |||
103 | ret = caam_jr_enqueue(jrdev, desc, split_key_done, &result); | ||
104 | if (!ret) { | ||
105 | /* in progress */ | ||
106 | wait_for_completion_interruptible(&result.completion); | ||
107 | ret = result.err; | ||
108 | #ifdef DEBUG | ||
109 | print_hex_dump(KERN_ERR, "ctx.key@"xstr(__LINE__)": ", | ||
110 | DUMP_PREFIX_ADDRESS, 16, 4, key_out, | ||
111 | split_key_pad_len, 1); | ||
112 | #endif | ||
113 | } | ||
114 | |||
115 | dma_unmap_single(jrdev, dma_addr_out, split_key_pad_len, | ||
116 | DMA_FROM_DEVICE); | ||
117 | dma_unmap_single(jrdev, dma_addr_in, keylen, DMA_TO_DEVICE); | ||
118 | |||
119 | kfree(desc); | ||
120 | |||
121 | return ret; | ||
122 | } | ||
diff --git a/drivers/crypto/caam/key_gen.h b/drivers/crypto/caam/key_gen.h new file mode 100644 index 000000000000..d95d290c6e8b --- /dev/null +++ b/drivers/crypto/caam/key_gen.h | |||
@@ -0,0 +1,17 @@ | |||
1 | /* | ||
2 | * CAAM/SEC 4.x definitions for handling key-generation jobs | ||
3 | * | ||
4 | * Copyright 2008-2011 Freescale Semiconductor, Inc. | ||
5 | * | ||
6 | */ | ||
7 | |||
8 | struct split_key_result { | ||
9 | struct completion completion; | ||
10 | int err; | ||
11 | }; | ||
12 | |||
13 | void split_key_done(struct device *dev, u32 *desc, u32 err, void *context); | ||
14 | |||
15 | u32 gen_split_key(struct device *jrdev, u8 *key_out, int split_key_len, | ||
16 | int split_key_pad_len, const u8 *key_in, u32 keylen, | ||
17 | u32 alg_op); | ||
diff --git a/drivers/crypto/caam/sg_link_tbl.h b/drivers/crypto/caam/sg_link_tbl.h new file mode 100644 index 000000000000..6df434922460 --- /dev/null +++ b/drivers/crypto/caam/sg_link_tbl.h | |||
@@ -0,0 +1,84 @@ | |||
1 | /* | ||
2 | * CAAM/SEC 4.x functions for using scatterlists in caam driver | ||
3 | * | ||
4 | * Copyright 2008-2011 Freescale Semiconductor, Inc. | ||
5 | * | ||
6 | */ | ||
7 | |||
8 | struct link_tbl_entry; | ||
9 | |||
10 | /* | ||
11 | * convert single dma address to h/w link table format | ||
12 | */ | ||
13 | static inline void sg_to_link_tbl_one(struct link_tbl_entry *link_tbl_ptr, | ||
14 | dma_addr_t dma, u32 len, u32 offset) | ||
15 | { | ||
16 | link_tbl_ptr->ptr = dma; | ||
17 | link_tbl_ptr->len = len; | ||
18 | link_tbl_ptr->reserved = 0; | ||
19 | link_tbl_ptr->buf_pool_id = 0; | ||
20 | link_tbl_ptr->offset = offset; | ||
21 | #ifdef DEBUG | ||
22 | print_hex_dump(KERN_ERR, "link_tbl_ptr@: ", | ||
23 | DUMP_PREFIX_ADDRESS, 16, 4, link_tbl_ptr, | ||
24 | sizeof(struct link_tbl_entry), 1); | ||
25 | #endif | ||
26 | } | ||
27 | |||
28 | /* | ||
29 | * convert scatterlist to h/w link table format | ||
30 | * but does not have final bit; instead, returns last entry | ||
31 | */ | ||
32 | static inline struct link_tbl_entry * | ||
33 | sg_to_link_tbl(struct scatterlist *sg, int sg_count, | ||
34 | struct link_tbl_entry *link_tbl_ptr, u32 offset) | ||
35 | { | ||
36 | while (sg_count) { | ||
37 | sg_to_link_tbl_one(link_tbl_ptr, sg_dma_address(sg), | ||
38 | sg_dma_len(sg), offset); | ||
39 | link_tbl_ptr++; | ||
40 | sg = sg_next(sg); | ||
41 | sg_count--; | ||
42 | } | ||
43 | return link_tbl_ptr - 1; | ||
44 | } | ||
45 | |||
46 | /* | ||
47 | * convert scatterlist to h/w link table format | ||
48 | * scatterlist must have been previously dma mapped | ||
49 | */ | ||
50 | static inline void sg_to_link_tbl_last(struct scatterlist *sg, int sg_count, | ||
51 | struct link_tbl_entry *link_tbl_ptr, | ||
52 | u32 offset) | ||
53 | { | ||
54 | link_tbl_ptr = sg_to_link_tbl(sg, sg_count, link_tbl_ptr, offset); | ||
55 | link_tbl_ptr->len |= LINK_TBL_LEN_FIN; | ||
56 | } | ||
57 | |||
58 | /* count number of elements in scatterlist */ | ||
59 | static inline int __sg_count(struct scatterlist *sg_list, int nbytes) | ||
60 | { | ||
61 | struct scatterlist *sg = sg_list; | ||
62 | int sg_nents = 0; | ||
63 | |||
64 | while (nbytes > 0) { | ||
65 | sg_nents++; | ||
66 | nbytes -= sg->length; | ||
67 | if (!sg_is_last(sg) && (sg + 1)->length == 0) | ||
68 | BUG(); /* Not support chaining */ | ||
69 | sg = scatterwalk_sg_next(sg); | ||
70 | } | ||
71 | |||
72 | return sg_nents; | ||
73 | } | ||
74 | |||
75 | /* derive number of elements in scatterlist, but return 0 for 1 */ | ||
76 | static inline int sg_count(struct scatterlist *sg_list, int nbytes) | ||
77 | { | ||
78 | int sg_nents = __sg_count(sg_list, nbytes); | ||
79 | |||
80 | if (likely(sg_nents == 1)) | ||
81 | return 0; | ||
82 | |||
83 | return sg_nents; | ||
84 | } | ||