Commit 78506c2a1eac97504ff56de1c587bac403ca8dca
Committed by
Herbert Xu
1 parent
6450601703
crypto: octeontx2 - add support to get engine capabilities
Adds support to get engine capabilities and adds a new mailbox to share capabilities with VF driver. Signed-off-by: Suheil Chandran <schandran@marvell.com> Signed-off-by: Srujana Challa <schalla@marvell.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Showing 8 changed files with 350 additions and 0 deletions Side-by-side Diff
- drivers/crypto/marvell/octeontx2/otx2_cpt_common.h
- drivers/crypto/marvell/octeontx2/otx2_cpt_reqmgr.h
- drivers/crypto/marvell/octeontx2/otx2_cptlf.h
- drivers/crypto/marvell/octeontx2/otx2_cptpf.h
- drivers/crypto/marvell/octeontx2/otx2_cptpf_main.c
- drivers/crypto/marvell/octeontx2/otx2_cptpf_mbox.c
- drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c
- drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.h
drivers/crypto/marvell/octeontx2/otx2_cpt_common.h
... | ... | @@ -20,6 +20,7 @@ |
20 | 20 | |
21 | 21 | #define OTX2_CPT_INVALID_CRYPTO_ENG_GRP 0xFF |
22 | 22 | #define OTX2_CPT_NAME_LENGTH 64 |
23 | +#define OTX2_CPT_DMA_MINALIGN 128 | |
23 | 24 | |
24 | 25 | #define BAD_OTX2_CPT_ENG_TYPE OTX2_CPT_MAX_ENG_TYPES |
25 | 26 | |
... | ... | @@ -32,6 +33,7 @@ |
32 | 33 | |
33 | 34 | /* Take mbox id from end of CPT mbox range in AF (range 0xA00 - 0xBFF) */ |
34 | 35 | #define MBOX_MSG_GET_ENG_GRP_NUM 0xBFF |
36 | +#define MBOX_MSG_GET_CAPS 0xBFD | |
35 | 37 | |
36 | 38 | /* |
37 | 39 | * Message request and response to get engine group number |
... | ... | @@ -47,6 +49,40 @@ |
47 | 49 | struct mbox_msghdr hdr; |
48 | 50 | u8 eng_type; |
49 | 51 | u8 eng_grp_num; |
52 | +}; | |
53 | + | |
54 | +/* CPT HW capabilities */ | |
55 | +union otx2_cpt_eng_caps { | |
56 | + u64 u; | |
57 | + struct { | |
58 | + u64 reserved_0_4:5; | |
59 | + u64 mul:1; | |
60 | + u64 sha1_sha2:1; | |
61 | + u64 chacha20:1; | |
62 | + u64 zuc_snow3g:1; | |
63 | + u64 sha3:1; | |
64 | + u64 aes:1; | |
65 | + u64 kasumi:1; | |
66 | + u64 des:1; | |
67 | + u64 crc:1; | |
68 | + u64 reserved_14_63:50; | |
69 | + }; | |
70 | +}; | |
71 | + | |
72 | +/* | |
73 | + * Message request and response to get HW capabilities for each | |
74 | + * engine type (SE, IE, AE). | |
75 | + * This messages are only used between CPT PF <=> CPT VF | |
76 | + */ | |
77 | +struct otx2_cpt_caps_msg { | |
78 | + struct mbox_msghdr hdr; | |
79 | +}; | |
80 | + | |
81 | +struct otx2_cpt_caps_rsp { | |
82 | + struct mbox_msghdr hdr; | |
83 | + u16 cpt_pf_drv_version; | |
84 | + u8 cpt_revision; | |
85 | + union otx2_cpt_eng_caps eng_caps[OTX2_CPT_MAX_ENG_TYPES]; | |
50 | 86 | }; |
51 | 87 | |
52 | 88 | static inline void otx2_cpt_write64(void __iomem *reg_base, u64 blk, u64 slot, |
drivers/crypto/marvell/octeontx2/otx2_cpt_reqmgr.h
1 | +/* SPDX-License-Identifier: GPL-2.0-only | |
2 | + * Copyright (C) 2020 Marvell. | |
3 | + */ | |
4 | + | |
5 | +#ifndef __OTX2_CPT_REQMGR_H | |
6 | +#define __OTX2_CPT_REQMGR_H | |
7 | + | |
8 | +#include "otx2_cpt_common.h" | |
9 | + | |
10 | +/* Completion code size and initial value */ | |
11 | +#define OTX2_CPT_COMPLETION_CODE_SIZE 8 | |
12 | +#define OTX2_CPT_COMPLETION_CODE_INIT OTX2_CPT_COMP_E_NOTDONE | |
13 | + | |
14 | +union otx2_cpt_opcode { | |
15 | + u16 flags; | |
16 | + struct { | |
17 | + u8 major; | |
18 | + u8 minor; | |
19 | + } s; | |
20 | +}; | |
21 | + | |
22 | +/* | |
23 | + * CPT_INST_S software command definitions | |
24 | + * Words EI (0-3) | |
25 | + */ | |
26 | +union otx2_cpt_iq_cmd_word0 { | |
27 | + u64 u; | |
28 | + struct { | |
29 | + __be16 opcode; | |
30 | + __be16 param1; | |
31 | + __be16 param2; | |
32 | + __be16 dlen; | |
33 | + } s; | |
34 | +}; | |
35 | + | |
36 | +union otx2_cpt_iq_cmd_word3 { | |
37 | + u64 u; | |
38 | + struct { | |
39 | + u64 cptr:61; | |
40 | + u64 grp:3; | |
41 | + } s; | |
42 | +}; | |
43 | + | |
44 | +struct otx2_cpt_iq_command { | |
45 | + union otx2_cpt_iq_cmd_word0 cmd; | |
46 | + u64 dptr; | |
47 | + u64 rptr; | |
48 | + union otx2_cpt_iq_cmd_word3 cptr; | |
49 | +}; | |
50 | + | |
51 | +#endif /* __OTX2_CPT_REQMGR_H */ |
drivers/crypto/marvell/octeontx2/otx2_cptlf.h
... | ... | @@ -4,9 +4,11 @@ |
4 | 4 | #ifndef __OTX2_CPTLF_H |
5 | 5 | #define __OTX2_CPTLF_H |
6 | 6 | |
7 | +#include <linux/soc/marvell/octeontx2/asm.h> | |
7 | 8 | #include <mbox.h> |
8 | 9 | #include <rvu.h> |
9 | 10 | #include "otx2_cpt_common.h" |
11 | +#include "otx2_cpt_reqmgr.h" | |
10 | 12 | |
11 | 13 | /* |
12 | 14 | * CPT instruction and pending queues user requested length in CPT_INST_S msgs |
... | ... | @@ -270,6 +272,66 @@ |
270 | 272 | otx2_cptlf_enable_iqueue_exec(&lfs->lf[slot]); |
271 | 273 | otx2_cptlf_enable_iqueue_enq(&lfs->lf[slot]); |
272 | 274 | } |
275 | +} | |
276 | + | |
277 | +static inline void otx2_cpt_fill_inst(union otx2_cpt_inst_s *cptinst, | |
278 | + struct otx2_cpt_iq_command *iq_cmd, | |
279 | + u64 comp_baddr) | |
280 | +{ | |
281 | + cptinst->u[0] = 0x0; | |
282 | + cptinst->s.doneint = true; | |
283 | + cptinst->s.res_addr = comp_baddr; | |
284 | + cptinst->u[2] = 0x0; | |
285 | + cptinst->u[3] = 0x0; | |
286 | + cptinst->s.ei0 = iq_cmd->cmd.u; | |
287 | + cptinst->s.ei1 = iq_cmd->dptr; | |
288 | + cptinst->s.ei2 = iq_cmd->rptr; | |
289 | + cptinst->s.ei3 = iq_cmd->cptr.u; | |
290 | +} | |
291 | + | |
292 | +/* | |
293 | + * On OcteonTX2 platform the parameter insts_num is used as a count of | |
294 | + * instructions to be enqueued. The valid values for insts_num are: | |
295 | + * 1 - 1 CPT instruction will be enqueued during LMTST operation | |
296 | + * 2 - 2 CPT instructions will be enqueued during LMTST operation | |
297 | + */ | |
298 | +static inline void otx2_cpt_send_cmd(union otx2_cpt_inst_s *cptinst, | |
299 | + u32 insts_num, struct otx2_cptlf_info *lf) | |
300 | +{ | |
301 | + void __iomem *lmtline = lf->lmtline; | |
302 | + long ret; | |
303 | + | |
304 | + /* | |
305 | + * Make sure memory areas pointed in CPT_INST_S | |
306 | + * are flushed before the instruction is sent to CPT | |
307 | + */ | |
308 | + dma_wmb(); | |
309 | + | |
310 | + do { | |
311 | + /* Copy CPT command to LMTLINE */ | |
312 | + memcpy_toio(lmtline, cptinst, insts_num * OTX2_CPT_INST_SIZE); | |
313 | + | |
314 | + /* | |
315 | + * LDEOR initiates atomic transfer to I/O device | |
316 | + * The following will cause the LMTST to fail (the LDEOR | |
317 | + * returns zero): | |
318 | + * - No stores have been performed to the LMTLINE since it was | |
319 | + * last invalidated. | |
320 | + * - The bytes which have been stored to LMTLINE since it was | |
321 | + * last invalidated form a pattern that is non-contiguous, does | |
322 | + * not start at byte 0, or does not end on a 8-byte boundary. | |
323 | + * (i.e.comprises a formation of other than 1โ16 8-byte | |
324 | + * words.) | |
325 | + * | |
326 | + * These rules are designed such that an operating system | |
327 | + * context switch or hypervisor guest switch need have no | |
328 | + * knowledge of the LMTST operations; the switch code does not | |
329 | + * need to store to LMTCANCEL. Also note as LMTLINE data cannot | |
330 | + * be read, there is no information leakage between processes. | |
331 | + */ | |
332 | + ret = otx2_lmt_flush(lf->ioreg); | |
333 | + | |
334 | + } while (!ret); | |
273 | 335 | } |
274 | 336 | |
275 | 337 | int otx2_cptlf_init(struct otx2_cptlfs_info *lfs, u8 eng_grp_msk, int pri, |
drivers/crypto/marvell/octeontx2/otx2_cptpf.h
... | ... | @@ -31,6 +31,9 @@ |
31 | 31 | struct otx2_cptvf_info vf[OTX2_CPT_MAX_VFS_NUM]; |
32 | 32 | struct otx2_cpt_eng_grps eng_grps;/* Engine groups information */ |
33 | 33 | struct otx2_cptlfs_info lfs; /* CPT LFs attached to this PF */ |
34 | + /* HW capabilities for each engine type */ | |
35 | + union otx2_cpt_eng_caps eng_caps[OTX2_CPT_MAX_ENG_TYPES]; | |
36 | + bool is_eng_caps_discovered; | |
34 | 37 | |
35 | 38 | /* AF <=> PF mbox */ |
36 | 39 | struct otx2_mbox afpf_mbox; |
drivers/crypto/marvell/octeontx2/otx2_cptpf_main.c
... | ... | @@ -500,6 +500,11 @@ |
500 | 500 | if (ret) |
501 | 501 | goto destroy_flr; |
502 | 502 | |
503 | + /* Get CPT HW capabilities using LOAD_FVC operation. */ | |
504 | + ret = otx2_cpt_discover_eng_capabilities(cptpf); | |
505 | + if (ret) | |
506 | + goto disable_intr; | |
507 | + | |
503 | 508 | ret = otx2_cpt_create_eng_grps(cptpf->pdev, &cptpf->eng_grps); |
504 | 509 | if (ret) |
505 | 510 | goto disable_intr; |
drivers/crypto/marvell/octeontx2/otx2_cptpf_mbox.c
... | ... | @@ -5,6 +5,12 @@ |
5 | 5 | #include "otx2_cptpf.h" |
6 | 6 | #include "rvu_reg.h" |
7 | 7 | |
8 | +/* | |
9 | + * CPT PF driver version, It will be incremented by 1 for every feature | |
10 | + * addition in CPT mailbox messages. | |
11 | + */ | |
12 | +#define OTX2_CPT_PF_DRV_VERSION 0x1 | |
13 | + | |
8 | 14 | static int forward_to_af(struct otx2_cptpf_dev *cptpf, |
9 | 15 | struct otx2_cptvf_info *vf, |
10 | 16 | struct mbox_msghdr *req, int size) |
... | ... | @@ -35,6 +41,28 @@ |
35 | 41 | return 0; |
36 | 42 | } |
37 | 43 | |
44 | +static int handle_msg_get_caps(struct otx2_cptpf_dev *cptpf, | |
45 | + struct otx2_cptvf_info *vf, | |
46 | + struct mbox_msghdr *req) | |
47 | +{ | |
48 | + struct otx2_cpt_caps_rsp *rsp; | |
49 | + | |
50 | + rsp = (struct otx2_cpt_caps_rsp *) | |
51 | + otx2_mbox_alloc_msg(&cptpf->vfpf_mbox, vf->vf_id, | |
52 | + sizeof(*rsp)); | |
53 | + if (!rsp) | |
54 | + return -ENOMEM; | |
55 | + | |
56 | + rsp->hdr.id = MBOX_MSG_GET_CAPS; | |
57 | + rsp->hdr.sig = OTX2_MBOX_RSP_SIG; | |
58 | + rsp->hdr.pcifunc = req->pcifunc; | |
59 | + rsp->cpt_pf_drv_version = OTX2_CPT_PF_DRV_VERSION; | |
60 | + rsp->cpt_revision = cptpf->pdev->revision; | |
61 | + memcpy(&rsp->eng_caps, &cptpf->eng_caps, sizeof(rsp->eng_caps)); | |
62 | + | |
63 | + return 0; | |
64 | +} | |
65 | + | |
38 | 66 | static int handle_msg_get_eng_grp_num(struct otx2_cptpf_dev *cptpf, |
39 | 67 | struct otx2_cptvf_info *vf, |
40 | 68 | struct mbox_msghdr *req) |
... | ... | @@ -71,6 +99,9 @@ |
71 | 99 | switch (req->id) { |
72 | 100 | case MBOX_MSG_GET_ENG_GRP_NUM: |
73 | 101 | err = handle_msg_get_eng_grp_num(cptpf, vf, req); |
102 | + break; | |
103 | + case MBOX_MSG_GET_CAPS: | |
104 | + err = handle_msg_get_caps(cptpf, vf, req); | |
74 | 105 | break; |
75 | 106 | default: |
76 | 107 | err = forward_to_af(cptpf, vf, req, size); |
drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c
... | ... | @@ -6,6 +6,8 @@ |
6 | 6 | #include "otx2_cptpf_ucode.h" |
7 | 7 | #include "otx2_cpt_common.h" |
8 | 8 | #include "otx2_cptpf.h" |
9 | +#include "otx2_cptlf.h" | |
10 | +#include "otx2_cpt_reqmgr.h" | |
9 | 11 | #include "rvu_reg.h" |
10 | 12 | |
11 | 13 | #define CSR_DELAY 30 |
... | ... | @@ -1250,6 +1252,165 @@ |
1250 | 1252 | |
1251 | 1253 | cleanup_eng_grps: |
1252 | 1254 | otx2_cpt_cleanup_eng_grps(pdev, eng_grps); |
1255 | + return ret; | |
1256 | +} | |
1257 | + | |
1258 | +static int create_eng_caps_discovery_grps(struct pci_dev *pdev, | |
1259 | + struct otx2_cpt_eng_grps *eng_grps) | |
1260 | +{ | |
1261 | + struct otx2_cpt_uc_info_t *uc_info[OTX2_CPT_MAX_ETYPES_PER_GRP] = { }; | |
1262 | + struct otx2_cpt_engines engs[OTX2_CPT_MAX_ETYPES_PER_GRP] = { {0} }; | |
1263 | + struct fw_info_t fw_info; | |
1264 | + int ret; | |
1265 | + | |
1266 | + ret = cpt_ucode_load_fw(pdev, &fw_info); | |
1267 | + if (ret) | |
1268 | + return ret; | |
1269 | + | |
1270 | + uc_info[0] = get_ucode(&fw_info, OTX2_CPT_SE_TYPES); | |
1271 | + if (uc_info[0] == NULL) { | |
1272 | + dev_err(&pdev->dev, "Unable to find firmware for AE\n"); | |
1273 | + ret = -EINVAL; | |
1274 | + goto release_fw; | |
1275 | + } | |
1276 | + engs[0].type = OTX2_CPT_AE_TYPES; | |
1277 | + engs[0].count = 2; | |
1278 | + | |
1279 | + ret = create_engine_group(&pdev->dev, eng_grps, engs, 1, | |
1280 | + (void **) uc_info, 0); | |
1281 | + if (ret) | |
1282 | + goto release_fw; | |
1283 | + | |
1284 | + uc_info[0] = get_ucode(&fw_info, OTX2_CPT_SE_TYPES); | |
1285 | + if (uc_info[0] == NULL) { | |
1286 | + dev_err(&pdev->dev, "Unable to find firmware for SE\n"); | |
1287 | + ret = -EINVAL; | |
1288 | + goto delete_eng_grp; | |
1289 | + } | |
1290 | + engs[0].type = OTX2_CPT_SE_TYPES; | |
1291 | + engs[0].count = 2; | |
1292 | + | |
1293 | + ret = create_engine_group(&pdev->dev, eng_grps, engs, 1, | |
1294 | + (void **) uc_info, 0); | |
1295 | + if (ret) | |
1296 | + goto delete_eng_grp; | |
1297 | + | |
1298 | + uc_info[0] = get_ucode(&fw_info, OTX2_CPT_IE_TYPES); | |
1299 | + if (uc_info[0] == NULL) { | |
1300 | + dev_err(&pdev->dev, "Unable to find firmware for IE\n"); | |
1301 | + ret = -EINVAL; | |
1302 | + goto delete_eng_grp; | |
1303 | + } | |
1304 | + engs[0].type = OTX2_CPT_IE_TYPES; | |
1305 | + engs[0].count = 2; | |
1306 | + | |
1307 | + ret = create_engine_group(&pdev->dev, eng_grps, engs, 1, | |
1308 | + (void **) uc_info, 0); | |
1309 | + if (ret) | |
1310 | + goto delete_eng_grp; | |
1311 | + | |
1312 | + cpt_ucode_release_fw(&fw_info); | |
1313 | + return 0; | |
1314 | + | |
1315 | +delete_eng_grp: | |
1316 | + delete_engine_grps(pdev, eng_grps); | |
1317 | +release_fw: | |
1318 | + cpt_ucode_release_fw(&fw_info); | |
1319 | + return ret; | |
1320 | +} | |
1321 | + | |
1322 | +/* | |
1323 | + * Get CPT HW capabilities using LOAD_FVC operation. | |
1324 | + */ | |
1325 | +int otx2_cpt_discover_eng_capabilities(struct otx2_cptpf_dev *cptpf) | |
1326 | +{ | |
1327 | + struct otx2_cptlfs_info *lfs = &cptpf->lfs; | |
1328 | + struct otx2_cpt_iq_command iq_cmd; | |
1329 | + union otx2_cpt_opcode opcode; | |
1330 | + union otx2_cpt_res_s *result; | |
1331 | + union otx2_cpt_inst_s inst; | |
1332 | + dma_addr_t rptr_baddr; | |
1333 | + struct pci_dev *pdev; | |
1334 | + u32 len, compl_rlen; | |
1335 | + int ret, etype; | |
1336 | + void *rptr; | |
1337 | + | |
1338 | + /* | |
1339 | + * We don't get capabilities if it was already done | |
1340 | + * (when user enabled VFs for the first time) | |
1341 | + */ | |
1342 | + if (cptpf->is_eng_caps_discovered) | |
1343 | + return 0; | |
1344 | + | |
1345 | + pdev = cptpf->pdev; | |
1346 | + /* | |
1347 | + * Create engine groups for each type to submit LOAD_FVC op and | |
1348 | + * get engine's capabilities. | |
1349 | + */ | |
1350 | + ret = create_eng_caps_discovery_grps(pdev, &cptpf->eng_grps); | |
1351 | + if (ret) | |
1352 | + goto delete_grps; | |
1353 | + | |
1354 | + lfs->pdev = pdev; | |
1355 | + lfs->reg_base = cptpf->reg_base; | |
1356 | + lfs->mbox = &cptpf->afpf_mbox; | |
1357 | + ret = otx2_cptlf_init(&cptpf->lfs, OTX2_CPT_ALL_ENG_GRPS_MASK, | |
1358 | + OTX2_CPT_QUEUE_HI_PRIO, 1); | |
1359 | + if (ret) | |
1360 | + goto delete_grps; | |
1361 | + | |
1362 | + compl_rlen = ALIGN(sizeof(union otx2_cpt_res_s), OTX2_CPT_DMA_MINALIGN); | |
1363 | + len = compl_rlen + LOADFVC_RLEN; | |
1364 | + | |
1365 | + result = kzalloc(len, GFP_KERNEL); | |
1366 | + if (!result) { | |
1367 | + ret = -ENOMEM; | |
1368 | + goto lf_cleanup; | |
1369 | + } | |
1370 | + rptr_baddr = dma_map_single(&pdev->dev, (void *)result, len, | |
1371 | + DMA_BIDIRECTIONAL); | |
1372 | + if (dma_mapping_error(&pdev->dev, rptr_baddr)) { | |
1373 | + dev_err(&pdev->dev, "DMA mapping failed\n"); | |
1374 | + ret = -EFAULT; | |
1375 | + goto free_result; | |
1376 | + } | |
1377 | + rptr = (u8 *)result + compl_rlen; | |
1378 | + | |
1379 | + /* Fill in the command */ | |
1380 | + opcode.s.major = LOADFVC_MAJOR_OP; | |
1381 | + opcode.s.minor = LOADFVC_MINOR_OP; | |
1382 | + | |
1383 | + iq_cmd.cmd.u = 0; | |
1384 | + iq_cmd.cmd.s.opcode = cpu_to_be16(opcode.flags); | |
1385 | + | |
1386 | + /* 64-bit swap for microcode data reads, not needed for addresses */ | |
1387 | + cpu_to_be64s(&iq_cmd.cmd.u); | |
1388 | + iq_cmd.dptr = 0; | |
1389 | + iq_cmd.rptr = rptr_baddr + compl_rlen; | |
1390 | + iq_cmd.cptr.u = 0; | |
1391 | + | |
1392 | + for (etype = 1; etype < OTX2_CPT_MAX_ENG_TYPES; etype++) { | |
1393 | + result->s.compcode = OTX2_CPT_COMPLETION_CODE_INIT; | |
1394 | + iq_cmd.cptr.s.grp = otx2_cpt_get_eng_grp(&cptpf->eng_grps, | |
1395 | + etype); | |
1396 | + otx2_cpt_fill_inst(&inst, &iq_cmd, rptr_baddr); | |
1397 | + otx2_cpt_send_cmd(&inst, 1, &cptpf->lfs.lf[0]); | |
1398 | + | |
1399 | + while (result->s.compcode == OTX2_CPT_COMPLETION_CODE_INIT) | |
1400 | + cpu_relax(); | |
1401 | + | |
1402 | + cptpf->eng_caps[etype].u = be64_to_cpup(rptr); | |
1403 | + } | |
1404 | + dma_unmap_single(&pdev->dev, rptr_baddr, len, DMA_BIDIRECTIONAL); | |
1405 | + cptpf->is_eng_caps_discovered = true; | |
1406 | + | |
1407 | +free_result: | |
1408 | + kfree(result); | |
1409 | +lf_cleanup: | |
1410 | + otx2_cptlf_shutdown(&cptpf->lfs); | |
1411 | +delete_grps: | |
1412 | + delete_engine_grps(pdev, &cptpf->eng_grps); | |
1413 | + | |
1253 | 1414 | return ret; |
1254 | 1415 | } |
drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.h
... | ... | @@ -157,6 +157,7 @@ |
157 | 157 | struct otx2_cpt_eng_grps *eng_grps); |
158 | 158 | int otx2_cpt_disable_all_cores(struct otx2_cptpf_dev *cptpf); |
159 | 159 | int otx2_cpt_get_eng_grp(struct otx2_cpt_eng_grps *eng_grps, int eng_type); |
160 | +int otx2_cpt_discover_eng_capabilities(struct otx2_cptpf_dev *cptpf); | |
160 | 161 | |
161 | 162 | #endif /* __OTX2_CPTPF_UCODE_H */ |