0001
0002
0003
0004
0005
0006 #include <linux/debugfs.h>
0007
0008 #include "cipher.h"
0009 #include "util.h"
0010
0011
0012 #define SPU_OFIFO_CTRL 0x40
0013 #define SPU_FIFO_WATERMARK 0x1FF
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027 int spu_sg_at_offset(struct scatterlist *sg, unsigned int skip,
0028 struct scatterlist **sge, unsigned int *sge_offset)
0029 {
0030
0031 unsigned int index = 0;
0032
0033 unsigned int next_index;
0034
0035 next_index = sg->length;
0036 while (next_index <= skip) {
0037 sg = sg_next(sg);
0038 index = next_index;
0039 if (!sg)
0040 return -EINVAL;
0041 next_index += sg->length;
0042 }
0043
0044 *sge_offset = skip - index;
0045 *sge = sg;
0046 return 0;
0047 }
0048
0049
0050 void sg_copy_part_to_buf(struct scatterlist *src, u8 *dest,
0051 unsigned int len, unsigned int skip)
0052 {
0053 size_t copied;
0054 unsigned int nents = sg_nents(src);
0055
0056 copied = sg_pcopy_to_buffer(src, nents, dest, len, skip);
0057 if (copied != len) {
0058 flow_log("%s copied %u bytes of %u requested. ",
0059 __func__, (u32)copied, len);
0060 flow_log("sg with %u entries and skip %u\n", nents, skip);
0061 }
0062 }
0063
0064
0065
0066
0067
0068
0069 void sg_copy_part_from_buf(struct scatterlist *dest, u8 *src,
0070 unsigned int len, unsigned int skip)
0071 {
0072 size_t copied;
0073 unsigned int nents = sg_nents(dest);
0074
0075 copied = sg_pcopy_from_buffer(dest, nents, src, len, skip);
0076 if (copied != len) {
0077 flow_log("%s copied %u bytes of %u requested. ",
0078 __func__, (u32)copied, len);
0079 flow_log("sg with %u entries and skip %u\n", nents, skip);
0080 }
0081 }
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093 int spu_sg_count(struct scatterlist *sg_list, unsigned int skip, int nbytes)
0094 {
0095 struct scatterlist *sg;
0096 int sg_nents = 0;
0097 unsigned int offset;
0098
0099 if (!sg_list)
0100 return 0;
0101
0102 if (spu_sg_at_offset(sg_list, skip, &sg, &offset) < 0)
0103 return 0;
0104
0105 while (sg && (nbytes > 0)) {
0106 sg_nents++;
0107 nbytes -= (sg->length - offset);
0108 offset = 0;
0109 sg = sg_next(sg);
0110 }
0111 return sg_nents;
0112 }
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133 u32 spu_msg_sg_add(struct scatterlist **to_sg,
0134 struct scatterlist **from_sg, u32 *from_skip,
0135 u8 from_nents, u32 length)
0136 {
0137 struct scatterlist *sg;
0138 struct scatterlist *to = *to_sg;
0139 struct scatterlist *from = *from_sg;
0140 u32 skip = *from_skip;
0141 u32 offset;
0142 int i;
0143 u32 entry_len = 0;
0144 u32 frag_len = 0;
0145 u32 copied = 0;
0146
0147 if (length == 0)
0148 return 0;
0149
0150 for_each_sg(from, sg, from_nents, i) {
0151
0152 entry_len = sg->length - skip;
0153 frag_len = min(entry_len, length - copied);
0154 offset = sg->offset + skip;
0155 if (frag_len)
0156 sg_set_page(to++, sg_page(sg), frag_len, offset);
0157 copied += frag_len;
0158 if (copied == entry_len) {
0159
0160 skip = 0;
0161 }
0162 if (copied == length)
0163 break;
0164 }
0165 *to_sg = to;
0166 *from_sg = sg;
0167 if (frag_len < entry_len)
0168 *from_skip = skip + frag_len;
0169 else
0170 *from_skip = 0;
0171
0172 return copied;
0173 }
0174
0175 void add_to_ctr(u8 *ctr_pos, unsigned int increment)
0176 {
0177 __be64 *high_be = (__be64 *)ctr_pos;
0178 __be64 *low_be = high_be + 1;
0179 u64 orig_low = __be64_to_cpu(*low_be);
0180 u64 new_low = orig_low + (u64)increment;
0181
0182 *low_be = __cpu_to_be64(new_low);
0183 if (new_low < orig_low)
0184
0185 *high_be = __cpu_to_be64(__be64_to_cpu(*high_be) + 1);
0186 }
0187
0188 struct sdesc {
0189 struct shash_desc shash;
0190 char ctx[];
0191 };
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210 int do_shash(unsigned char *name, unsigned char *result,
0211 const u8 *data1, unsigned int data1_len,
0212 const u8 *data2, unsigned int data2_len,
0213 const u8 *key, unsigned int key_len)
0214 {
0215 int rc;
0216 unsigned int size;
0217 struct crypto_shash *hash;
0218 struct sdesc *sdesc;
0219
0220 hash = crypto_alloc_shash(name, 0, 0);
0221 if (IS_ERR(hash)) {
0222 rc = PTR_ERR(hash);
0223 pr_err("%s: Crypto %s allocation error %d\n", __func__, name, rc);
0224 return rc;
0225 }
0226
0227 size = sizeof(struct shash_desc) + crypto_shash_descsize(hash);
0228 sdesc = kmalloc(size, GFP_KERNEL);
0229 if (!sdesc) {
0230 rc = -ENOMEM;
0231 goto do_shash_err;
0232 }
0233 sdesc->shash.tfm = hash;
0234
0235 if (key_len > 0) {
0236 rc = crypto_shash_setkey(hash, key, key_len);
0237 if (rc) {
0238 pr_err("%s: Could not setkey %s shash\n", __func__, name);
0239 goto do_shash_err;
0240 }
0241 }
0242
0243 rc = crypto_shash_init(&sdesc->shash);
0244 if (rc) {
0245 pr_err("%s: Could not init %s shash\n", __func__, name);
0246 goto do_shash_err;
0247 }
0248 rc = crypto_shash_update(&sdesc->shash, data1, data1_len);
0249 if (rc) {
0250 pr_err("%s: Could not update1\n", __func__);
0251 goto do_shash_err;
0252 }
0253 if (data2 && data2_len) {
0254 rc = crypto_shash_update(&sdesc->shash, data2, data2_len);
0255 if (rc) {
0256 pr_err("%s: Could not update2\n", __func__);
0257 goto do_shash_err;
0258 }
0259 }
0260 rc = crypto_shash_final(&sdesc->shash, result);
0261 if (rc)
0262 pr_err("%s: Could not generate %s hash\n", __func__, name);
0263
0264 do_shash_err:
0265 crypto_free_shash(hash);
0266 kfree(sdesc);
0267
0268 return rc;
0269 }
0270
0271 #ifdef DEBUG
0272
0273 void __dump_sg(struct scatterlist *sg, unsigned int skip, unsigned int len)
0274 {
0275 u8 dbuf[16];
0276 unsigned int idx = skip;
0277 unsigned int num_out = 0;
0278 unsigned int count;
0279
0280 if (packet_debug_logging) {
0281 while (num_out < len) {
0282 count = (len - num_out > 16) ? 16 : len - num_out;
0283 sg_copy_part_to_buf(sg, dbuf, count, idx);
0284 num_out += count;
0285 print_hex_dump(KERN_ALERT, " sg: ", DUMP_PREFIX_NONE,
0286 4, 1, dbuf, count, false);
0287 idx += 16;
0288 }
0289 }
0290 if (debug_logging_sleep)
0291 msleep(debug_logging_sleep);
0292 }
0293 #endif
0294
0295
0296 char *spu_alg_name(enum spu_cipher_alg alg, enum spu_cipher_mode mode)
0297 {
0298 switch (alg) {
0299 case CIPHER_ALG_RC4:
0300 return "rc4";
0301 case CIPHER_ALG_AES:
0302 switch (mode) {
0303 case CIPHER_MODE_CBC:
0304 return "cbc(aes)";
0305 case CIPHER_MODE_ECB:
0306 return "ecb(aes)";
0307 case CIPHER_MODE_OFB:
0308 return "ofb(aes)";
0309 case CIPHER_MODE_CFB:
0310 return "cfb(aes)";
0311 case CIPHER_MODE_CTR:
0312 return "ctr(aes)";
0313 case CIPHER_MODE_XTS:
0314 return "xts(aes)";
0315 case CIPHER_MODE_GCM:
0316 return "gcm(aes)";
0317 default:
0318 return "aes";
0319 }
0320 break;
0321 case CIPHER_ALG_DES:
0322 switch (mode) {
0323 case CIPHER_MODE_CBC:
0324 return "cbc(des)";
0325 case CIPHER_MODE_ECB:
0326 return "ecb(des)";
0327 case CIPHER_MODE_CTR:
0328 return "ctr(des)";
0329 default:
0330 return "des";
0331 }
0332 break;
0333 case CIPHER_ALG_3DES:
0334 switch (mode) {
0335 case CIPHER_MODE_CBC:
0336 return "cbc(des3_ede)";
0337 case CIPHER_MODE_ECB:
0338 return "ecb(des3_ede)";
0339 case CIPHER_MODE_CTR:
0340 return "ctr(des3_ede)";
0341 default:
0342 return "3des";
0343 }
0344 break;
0345 default:
0346 return "other";
0347 }
0348 }
0349
0350 static ssize_t spu_debugfs_read(struct file *filp, char __user *ubuf,
0351 size_t count, loff_t *offp)
0352 {
0353 struct bcm_device_private *ipriv;
0354 char *buf;
0355 ssize_t ret, out_offset, out_count;
0356 int i;
0357 u32 fifo_len;
0358 u32 spu_ofifo_ctrl;
0359 u32 alg;
0360 u32 mode;
0361 u32 op_cnt;
0362
0363 out_count = 2048;
0364
0365 buf = kmalloc(out_count, GFP_KERNEL);
0366 if (!buf)
0367 return -ENOMEM;
0368
0369 ipriv = filp->private_data;
0370 out_offset = 0;
0371 out_offset += scnprintf(buf + out_offset, out_count - out_offset,
0372 "Number of SPUs.........%u\n",
0373 ipriv->spu.num_spu);
0374 out_offset += scnprintf(buf + out_offset, out_count - out_offset,
0375 "Current sessions.......%u\n",
0376 atomic_read(&ipriv->session_count));
0377 out_offset += scnprintf(buf + out_offset, out_count - out_offset,
0378 "Session count..........%u\n",
0379 atomic_read(&ipriv->stream_count));
0380 out_offset += scnprintf(buf + out_offset, out_count - out_offset,
0381 "Cipher setkey..........%u\n",
0382 atomic_read(&ipriv->setkey_cnt[SPU_OP_CIPHER]));
0383 out_offset += scnprintf(buf + out_offset, out_count - out_offset,
0384 "Cipher Ops.............%u\n",
0385 atomic_read(&ipriv->op_counts[SPU_OP_CIPHER]));
0386 for (alg = 0; alg < CIPHER_ALG_LAST; alg++) {
0387 for (mode = 0; mode < CIPHER_MODE_LAST; mode++) {
0388 op_cnt = atomic_read(&ipriv->cipher_cnt[alg][mode]);
0389 if (op_cnt) {
0390 out_offset += scnprintf(buf + out_offset,
0391 out_count - out_offset,
0392 " %-13s%11u\n",
0393 spu_alg_name(alg, mode), op_cnt);
0394 }
0395 }
0396 }
0397 out_offset += scnprintf(buf + out_offset, out_count - out_offset,
0398 "Hash Ops...............%u\n",
0399 atomic_read(&ipriv->op_counts[SPU_OP_HASH]));
0400 for (alg = 0; alg < HASH_ALG_LAST; alg++) {
0401 op_cnt = atomic_read(&ipriv->hash_cnt[alg]);
0402 if (op_cnt) {
0403 out_offset += scnprintf(buf + out_offset,
0404 out_count - out_offset,
0405 " %-13s%11u\n",
0406 hash_alg_name[alg], op_cnt);
0407 }
0408 }
0409 out_offset += scnprintf(buf + out_offset, out_count - out_offset,
0410 "HMAC setkey............%u\n",
0411 atomic_read(&ipriv->setkey_cnt[SPU_OP_HMAC]));
0412 out_offset += scnprintf(buf + out_offset, out_count - out_offset,
0413 "HMAC Ops...............%u\n",
0414 atomic_read(&ipriv->op_counts[SPU_OP_HMAC]));
0415 for (alg = 0; alg < HASH_ALG_LAST; alg++) {
0416 op_cnt = atomic_read(&ipriv->hmac_cnt[alg]);
0417 if (op_cnt) {
0418 out_offset += scnprintf(buf + out_offset,
0419 out_count - out_offset,
0420 " %-13s%11u\n",
0421 hash_alg_name[alg], op_cnt);
0422 }
0423 }
0424 out_offset += scnprintf(buf + out_offset, out_count - out_offset,
0425 "AEAD setkey............%u\n",
0426 atomic_read(&ipriv->setkey_cnt[SPU_OP_AEAD]));
0427
0428 out_offset += scnprintf(buf + out_offset, out_count - out_offset,
0429 "AEAD Ops...............%u\n",
0430 atomic_read(&ipriv->op_counts[SPU_OP_AEAD]));
0431 for (alg = 0; alg < AEAD_TYPE_LAST; alg++) {
0432 op_cnt = atomic_read(&ipriv->aead_cnt[alg]);
0433 if (op_cnt) {
0434 out_offset += scnprintf(buf + out_offset,
0435 out_count - out_offset,
0436 " %-13s%11u\n",
0437 aead_alg_name[alg], op_cnt);
0438 }
0439 }
0440 out_offset += scnprintf(buf + out_offset, out_count - out_offset,
0441 "Bytes of req data......%llu\n",
0442 (u64)atomic64_read(&ipriv->bytes_out));
0443 out_offset += scnprintf(buf + out_offset, out_count - out_offset,
0444 "Bytes of resp data.....%llu\n",
0445 (u64)atomic64_read(&ipriv->bytes_in));
0446 out_offset += scnprintf(buf + out_offset, out_count - out_offset,
0447 "Mailbox full...........%u\n",
0448 atomic_read(&ipriv->mb_no_spc));
0449 out_offset += scnprintf(buf + out_offset, out_count - out_offset,
0450 "Mailbox send failures..%u\n",
0451 atomic_read(&ipriv->mb_send_fail));
0452 out_offset += scnprintf(buf + out_offset, out_count - out_offset,
0453 "Check ICV errors.......%u\n",
0454 atomic_read(&ipriv->bad_icv));
0455 if (ipriv->spu.spu_type == SPU_TYPE_SPUM)
0456 for (i = 0; i < ipriv->spu.num_spu; i++) {
0457 spu_ofifo_ctrl = ioread32(ipriv->spu.reg_vbase[i] +
0458 SPU_OFIFO_CTRL);
0459 fifo_len = spu_ofifo_ctrl & SPU_FIFO_WATERMARK;
0460 out_offset += scnprintf(buf + out_offset,
0461 out_count - out_offset,
0462 "SPU %d output FIFO high water.....%u\n",
0463 i, fifo_len);
0464 }
0465
0466 if (out_offset > out_count)
0467 out_offset = out_count;
0468
0469 ret = simple_read_from_buffer(ubuf, count, offp, buf, out_offset);
0470 kfree(buf);
0471 return ret;
0472 }
0473
0474 static const struct file_operations spu_debugfs_stats = {
0475 .owner = THIS_MODULE,
0476 .open = simple_open,
0477 .read = spu_debugfs_read,
0478 };
0479
0480
0481
0482
0483
0484
0485 void spu_setup_debugfs(void)
0486 {
0487 if (!debugfs_initialized())
0488 return;
0489
0490 if (!iproc_priv.debugfs_dir)
0491 iproc_priv.debugfs_dir = debugfs_create_dir(KBUILD_MODNAME,
0492 NULL);
0493
0494 if (!iproc_priv.debugfs_stats)
0495
0496 debugfs_create_file("stats", 0400, iproc_priv.debugfs_dir,
0497 &iproc_priv, &spu_debugfs_stats);
0498 }
0499
0500 void spu_free_debugfs(void)
0501 {
0502 debugfs_remove_recursive(iproc_priv.debugfs_dir);
0503 iproc_priv.debugfs_dir = NULL;
0504 }
0505
0506
0507
0508
0509
0510
0511
0512
0513
0514
0515
0516
0517 void format_value_ccm(unsigned int val, u8 *buf, u8 len)
0518 {
0519 int i;
0520
0521
0522 memset(buf, 0, len);
0523
0524
0525 for (i = 0; i < len; i++) {
0526 buf[len - i - 1] = (val >> (8 * i)) & 0xff;
0527 if (i >= 3)
0528 break;
0529 }
0530 }