1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright 2016 Broadcom
6 #include <linux/debugfs.h>
11 /* offset of SPU_OFIFO_CTRL register */
12 #define SPU_OFIFO_CTRL 0x40
13 #define SPU_FIFO_WATERMARK 0x1FF
16 * spu_sg_at_offset() - Find the scatterlist entry at a given distance from the
17 * start of a scatterlist.
18 * @sg: [in] Start of a scatterlist
19 * @skip: [in] Distance from the start of the scatterlist, in bytes
20 * @sge: [out] Scatterlist entry at skip bytes from start
21 * @sge_offset: [out] Number of bytes from start of sge buffer to get to
24 * Return: 0 if entry found at requested distance
27 int spu_sg_at_offset(struct scatterlist
*sg
, unsigned int skip
,
28 struct scatterlist
**sge
, unsigned int *sge_offset
)
30 /* byte index from start of sg to the end of the previous entry */
31 unsigned int index
= 0;
32 /* byte index from start of sg to the end of the current entry */
33 unsigned int next_index
;
35 next_index
= sg
->length
;
36 while (next_index
<= skip
) {
41 next_index
+= sg
->length
;
44 *sge_offset
= skip
- index
;
49 /* Copy len bytes of sg data, starting at offset skip, to a dest buffer */
50 void sg_copy_part_to_buf(struct scatterlist
*src
, u8
*dest
,
51 unsigned int len
, unsigned int skip
)
54 unsigned int nents
= sg_nents(src
);
56 copied
= sg_pcopy_to_buffer(src
, nents
, dest
, len
, skip
);
58 flow_log("%s copied %u bytes of %u requested. ",
59 __func__
, (u32
)copied
, len
);
60 flow_log("sg with %u entries and skip %u\n", nents
, skip
);
65 * Copy data into a scatterlist starting at a specified offset in the
66 * scatterlist. Specifically, copy len bytes of data in the buffer src
67 * into the scatterlist dest, starting skip bytes into the scatterlist.
69 void sg_copy_part_from_buf(struct scatterlist
*dest
, u8
*src
,
70 unsigned int len
, unsigned int skip
)
73 unsigned int nents
= sg_nents(dest
);
75 copied
= sg_pcopy_from_buffer(dest
, nents
, src
, len
, skip
);
77 flow_log("%s copied %u bytes of %u requested. ",
78 __func__
, (u32
)copied
, len
);
79 flow_log("sg with %u entries and skip %u\n", nents
, skip
);
84 * spu_sg_count() - Determine number of elements in scatterlist to provide a
85 * specified number of bytes.
86 * @sg_list: scatterlist to examine
87 * @skip: index of starting point
88 * @nbytes: consider elements of scatterlist until reaching this number of
91 * Return: the number of sg entries contributing to nbytes of data
93 int spu_sg_count(struct scatterlist
*sg_list
, unsigned int skip
, int nbytes
)
95 struct scatterlist
*sg
;
102 if (spu_sg_at_offset(sg_list
, skip
, &sg
, &offset
) < 0)
105 while (sg
&& (nbytes
> 0)) {
107 nbytes
-= (sg
->length
- offset
);
115 * spu_msg_sg_add() - Copy scatterlist entries from one sg to another, up to a
117 * @to_sg: scatterlist to copy to
118 * @from_sg: scatterlist to copy from
119 * @from_skip: number of bytes to skip in from_sg. Non-zero when previous
120 * request included part of the buffer in entry in from_sg.
121 * Assumes from_skip < from_sg->length.
122 * @from_nents number of entries in from_sg
123 * @length number of bytes to copy. may reach this limit before exhausting
126 * Copies the entries themselves, not the data in the entries. Assumes to_sg has
127 * enough entries. Does not limit the size of an individual buffer in to_sg.
129 * to_sg, from_sg, skip are all updated to end of copy
131 * Return: Number of bytes copied
133 u32
spu_msg_sg_add(struct scatterlist
**to_sg
,
134 struct scatterlist
**from_sg
, u32
*from_skip
,
135 u8 from_nents
, u32 length
)
137 struct scatterlist
*sg
; /* an entry in from_sg */
138 struct scatterlist
*to
= *to_sg
;
139 struct scatterlist
*from
= *from_sg
;
140 u32 skip
= *from_skip
;
144 u32 frag_len
= 0; /* length of entry added to to_sg */
145 u32 copied
= 0; /* number of bytes copied so far */
150 for_each_sg(from
, sg
, from_nents
, i
) {
151 /* number of bytes in this from entry not yet used */
152 entry_len
= sg
->length
- skip
;
153 frag_len
= min(entry_len
, length
- copied
);
154 offset
= sg
->offset
+ skip
;
156 sg_set_page(to
++, sg_page(sg
), frag_len
, offset
);
158 if (copied
== entry_len
) {
159 /* used up all of from entry */
160 skip
= 0; /* start at beginning of next entry */
162 if (copied
== length
)
167 if (frag_len
< entry_len
)
168 *from_skip
= skip
+ frag_len
;
175 void add_to_ctr(u8
*ctr_pos
, unsigned int increment
)
177 __be64
*high_be
= (__be64
*)ctr_pos
;
178 __be64
*low_be
= high_be
+ 1;
179 u64 orig_low
= __be64_to_cpu(*low_be
);
180 u64 new_low
= orig_low
+ (u64
)increment
;
182 *low_be
= __cpu_to_be64(new_low
);
183 if (new_low
< orig_low
)
184 /* there was a carry from the low 8 bytes */
185 *high_be
= __cpu_to_be64(__be64_to_cpu(*high_be
) + 1);
189 struct shash_desc shash
;
194 * do_shash() - Do a synchronous hash operation in software
195 * @name: The name of the hash algorithm
196 * @result: Buffer where digest is to be written
197 * @data1: First part of data to hash. May be NULL.
198 * @data1_len: Length of data1, in bytes
199 * @data2: Second part of data to hash. May be NULL.
200 * @data2_len: Length of data2, in bytes
201 * @key: Key (if keyed hash)
202 * @key_len: Length of key, in bytes (or 0 if non-keyed hash)
204 * Note that the crypto API will not select this driver's own transform because
205 * this driver only registers asynchronous algos.
207 * Return: 0 if hash successfully stored in result
210 int do_shash(unsigned char *name
, unsigned char *result
,
211 const u8
*data1
, unsigned int data1_len
,
212 const u8
*data2
, unsigned int data2_len
,
213 const u8
*key
, unsigned int key_len
)
217 struct crypto_shash
*hash
;
220 hash
= crypto_alloc_shash(name
, 0, 0);
223 pr_err("%s: Crypto %s allocation error %d\n", __func__
, name
, rc
);
227 size
= sizeof(struct shash_desc
) + crypto_shash_descsize(hash
);
228 sdesc
= kmalloc(size
, GFP_KERNEL
);
233 sdesc
->shash
.tfm
= hash
;
236 rc
= crypto_shash_setkey(hash
, key
, key_len
);
238 pr_err("%s: Could not setkey %s shash\n", __func__
, name
);
243 rc
= crypto_shash_init(&sdesc
->shash
);
245 pr_err("%s: Could not init %s shash\n", __func__
, name
);
248 rc
= crypto_shash_update(&sdesc
->shash
, data1
, data1_len
);
250 pr_err("%s: Could not update1\n", __func__
);
253 if (data2
&& data2_len
) {
254 rc
= crypto_shash_update(&sdesc
->shash
, data2
, data2_len
);
256 pr_err("%s: Could not update2\n", __func__
);
260 rc
= crypto_shash_final(&sdesc
->shash
, result
);
262 pr_err("%s: Could not generate %s hash\n", __func__
, name
);
265 crypto_free_shash(hash
);
271 /* Dump len bytes of a scatterlist starting at skip bytes into the sg */
272 void __dump_sg(struct scatterlist
*sg
, unsigned int skip
, unsigned int len
)
275 unsigned int idx
= skip
;
276 unsigned int num_out
= 0; /* number of bytes dumped so far */
279 if (packet_debug_logging
) {
280 while (num_out
< len
) {
281 count
= (len
- num_out
> 16) ? 16 : len
- num_out
;
282 sg_copy_part_to_buf(sg
, dbuf
, count
, idx
);
284 print_hex_dump(KERN_ALERT
, " sg: ", DUMP_PREFIX_NONE
,
285 4, 1, dbuf
, count
, false);
289 if (debug_logging_sleep
)
290 msleep(debug_logging_sleep
);
293 /* Returns the name for a given cipher alg/mode */
294 char *spu_alg_name(enum spu_cipher_alg alg
, enum spu_cipher_mode mode
)
301 case CIPHER_MODE_CBC
:
303 case CIPHER_MODE_ECB
:
305 case CIPHER_MODE_OFB
:
307 case CIPHER_MODE_CFB
:
309 case CIPHER_MODE_CTR
:
311 case CIPHER_MODE_XTS
:
313 case CIPHER_MODE_GCM
:
321 case CIPHER_MODE_CBC
:
323 case CIPHER_MODE_ECB
:
325 case CIPHER_MODE_CTR
:
331 case CIPHER_ALG_3DES
:
333 case CIPHER_MODE_CBC
:
334 return "cbc(des3_ede)";
335 case CIPHER_MODE_ECB
:
336 return "ecb(des3_ede)";
337 case CIPHER_MODE_CTR
:
338 return "ctr(des3_ede)";
348 static ssize_t
spu_debugfs_read(struct file
*filp
, char __user
*ubuf
,
349 size_t count
, loff_t
*offp
)
351 struct device_private
*ipriv
;
353 ssize_t ret
, out_offset
, out_count
;
363 buf
= kmalloc(out_count
, GFP_KERNEL
);
367 ipriv
= filp
->private_data
;
369 out_offset
+= scnprintf(buf
+ out_offset
, out_count
- out_offset
,
370 "Number of SPUs.........%u\n",
372 out_offset
+= scnprintf(buf
+ out_offset
, out_count
- out_offset
,
373 "Current sessions.......%u\n",
374 atomic_read(&ipriv
->session_count
));
375 out_offset
+= scnprintf(buf
+ out_offset
, out_count
- out_offset
,
376 "Session count..........%u\n",
377 atomic_read(&ipriv
->stream_count
));
378 out_offset
+= scnprintf(buf
+ out_offset
, out_count
- out_offset
,
379 "Cipher setkey..........%u\n",
380 atomic_read(&ipriv
->setkey_cnt
[SPU_OP_CIPHER
]));
381 out_offset
+= scnprintf(buf
+ out_offset
, out_count
- out_offset
,
382 "Cipher Ops.............%u\n",
383 atomic_read(&ipriv
->op_counts
[SPU_OP_CIPHER
]));
384 for (alg
= 0; alg
< CIPHER_ALG_LAST
; alg
++) {
385 for (mode
= 0; mode
< CIPHER_MODE_LAST
; mode
++) {
386 op_cnt
= atomic_read(&ipriv
->cipher_cnt
[alg
][mode
]);
388 out_offset
+= scnprintf(buf
+ out_offset
,
389 out_count
- out_offset
,
391 spu_alg_name(alg
, mode
), op_cnt
);
395 out_offset
+= scnprintf(buf
+ out_offset
, out_count
- out_offset
,
396 "Hash Ops...............%u\n",
397 atomic_read(&ipriv
->op_counts
[SPU_OP_HASH
]));
398 for (alg
= 0; alg
< HASH_ALG_LAST
; alg
++) {
399 op_cnt
= atomic_read(&ipriv
->hash_cnt
[alg
]);
401 out_offset
+= scnprintf(buf
+ out_offset
,
402 out_count
- out_offset
,
404 hash_alg_name
[alg
], op_cnt
);
407 out_offset
+= scnprintf(buf
+ out_offset
, out_count
- out_offset
,
408 "HMAC setkey............%u\n",
409 atomic_read(&ipriv
->setkey_cnt
[SPU_OP_HMAC
]));
410 out_offset
+= scnprintf(buf
+ out_offset
, out_count
- out_offset
,
411 "HMAC Ops...............%u\n",
412 atomic_read(&ipriv
->op_counts
[SPU_OP_HMAC
]));
413 for (alg
= 0; alg
< HASH_ALG_LAST
; alg
++) {
414 op_cnt
= atomic_read(&ipriv
->hmac_cnt
[alg
]);
416 out_offset
+= scnprintf(buf
+ out_offset
,
417 out_count
- out_offset
,
419 hash_alg_name
[alg
], op_cnt
);
422 out_offset
+= scnprintf(buf
+ out_offset
, out_count
- out_offset
,
423 "AEAD setkey............%u\n",
424 atomic_read(&ipriv
->setkey_cnt
[SPU_OP_AEAD
]));
426 out_offset
+= scnprintf(buf
+ out_offset
, out_count
- out_offset
,
427 "AEAD Ops...............%u\n",
428 atomic_read(&ipriv
->op_counts
[SPU_OP_AEAD
]));
429 for (alg
= 0; alg
< AEAD_TYPE_LAST
; alg
++) {
430 op_cnt
= atomic_read(&ipriv
->aead_cnt
[alg
]);
432 out_offset
+= scnprintf(buf
+ out_offset
,
433 out_count
- out_offset
,
435 aead_alg_name
[alg
], op_cnt
);
438 out_offset
+= scnprintf(buf
+ out_offset
, out_count
- out_offset
,
439 "Bytes of req data......%llu\n",
440 (u64
)atomic64_read(&ipriv
->bytes_out
));
441 out_offset
+= scnprintf(buf
+ out_offset
, out_count
- out_offset
,
442 "Bytes of resp data.....%llu\n",
443 (u64
)atomic64_read(&ipriv
->bytes_in
));
444 out_offset
+= scnprintf(buf
+ out_offset
, out_count
- out_offset
,
445 "Mailbox full...........%u\n",
446 atomic_read(&ipriv
->mb_no_spc
));
447 out_offset
+= scnprintf(buf
+ out_offset
, out_count
- out_offset
,
448 "Mailbox send failures..%u\n",
449 atomic_read(&ipriv
->mb_send_fail
));
450 out_offset
+= scnprintf(buf
+ out_offset
, out_count
- out_offset
,
451 "Check ICV errors.......%u\n",
452 atomic_read(&ipriv
->bad_icv
));
453 if (ipriv
->spu
.spu_type
== SPU_TYPE_SPUM
)
454 for (i
= 0; i
< ipriv
->spu
.num_spu
; i
++) {
455 spu_ofifo_ctrl
= ioread32(ipriv
->spu
.reg_vbase
[i
] +
457 fifo_len
= spu_ofifo_ctrl
& SPU_FIFO_WATERMARK
;
458 out_offset
+= scnprintf(buf
+ out_offset
,
459 out_count
- out_offset
,
460 "SPU %d output FIFO high water.....%u\n",
464 if (out_offset
> out_count
)
465 out_offset
= out_count
;
467 ret
= simple_read_from_buffer(ubuf
, count
, offp
, buf
, out_offset
);
472 static const struct file_operations spu_debugfs_stats
= {
473 .owner
= THIS_MODULE
,
475 .read
= spu_debugfs_read
,
479 * Create the debug FS directories. If the top-level directory has not yet
480 * been created, create it now. Create a stats file in this directory for
483 void spu_setup_debugfs(void)
485 if (!debugfs_initialized())
488 if (!iproc_priv
.debugfs_dir
)
489 iproc_priv
.debugfs_dir
= debugfs_create_dir(KBUILD_MODNAME
,
492 if (!iproc_priv
.debugfs_stats
)
493 /* Create file with permissions S_IRUSR */
494 debugfs_create_file("stats", 0400, iproc_priv
.debugfs_dir
,
495 &iproc_priv
, &spu_debugfs_stats
);
498 void spu_free_debugfs(void)
500 debugfs_remove_recursive(iproc_priv
.debugfs_dir
);
501 iproc_priv
.debugfs_dir
= NULL
;
505 * format_value_ccm() - Format a value into a buffer, using a specified number
506 * of bytes (i.e. maybe writing value X into a 4 byte
507 * buffer, or maybe into a 12 byte buffer), as per the
510 * @val: value to write (up to max of unsigned int)
511 * @buf: (pointer to) buffer to write the value
512 * @len: number of bytes to use (0 to 255)
515 void format_value_ccm(unsigned int val
, u8
*buf
, u8 len
)
519 /* First clear full output buffer */
522 /* Then, starting from right side, fill in with data */
523 for (i
= 0; i
< len
; i
++) {
524 buf
[len
- i
- 1] = (val
>> (8 * i
)) & 0xff;
526 break; /* Only handle up to 32 bits of 'val' */