Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

crypto: cavium - Add the Virtual Function driver for CPT

Enable the CPT VF driver. CPT is the cryptographic Acceleration Unit
in Octeon-tx series of processors.

Signed-off-by: George Cherian <george.cherian@cavium.com>
Reviewed-by: David Daney <david.daney@cavium.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

George Cherian and committed by
Herbert Xu
c694b233 9e2c7d99

+2581 -1
+2 -1
drivers/crypto/cavium/cpt/Makefile
··· 1 - obj-$(CONFIG_CAVIUM_CPT) += cptpf.o 1 + obj-$(CONFIG_CAVIUM_CPT) += cptpf.o cptvf.o 2 2 cptpf-objs := cptpf_main.o cptpf_mbox.o 3 + cptvf-objs := cptvf_main.o cptvf_reqmanager.o cptvf_mbox.o cptvf_algs.o
+135
drivers/crypto/cavium/cpt/cptvf.h
··· 1 + /* 2 + * Copyright (C) 2016 Cavium, Inc. 3 + * 4 + * This program is free software; you can redistribute it and/or modify it 5 + * under the terms of version 2 of the GNU General Public License 6 + * as published by the Free Software Foundation. 7 + */ 8 + 9 + #ifndef __CPTVF_H 10 + #define __CPTVF_H 11 + 12 + #include <linux/list.h> 13 + #include "cpt_common.h" 14 + 15 + /* Default command queue length */ 16 + #define CPT_CMD_QLEN 2046 17 + #define CPT_CMD_QCHUNK_SIZE 1023 18 + 19 + /* Default command timeout in seconds */ 20 + #define CPT_COMMAND_TIMEOUT 4 21 + #define CPT_TIMER_THOLD 0xFFFF 22 + #define CPT_NUM_QS_PER_VF 1 23 + #define CPT_INST_SIZE 64 24 + #define CPT_NEXT_CHUNK_PTR_SIZE 8 25 + 26 + #define CPT_VF_MSIX_VECTORS 2 27 + #define CPT_VF_INTR_MBOX_MASK BIT(0) 28 + #define CPT_VF_INTR_DOVF_MASK BIT(1) 29 + #define CPT_VF_INTR_IRDE_MASK BIT(2) 30 + #define CPT_VF_INTR_NWRP_MASK BIT(3) 31 + #define CPT_VF_INTR_SERR_MASK BIT(4) 32 + #define DMA_DIRECT_DIRECT 0 /* Input DIRECT, Output DIRECT */ 33 + #define DMA_GATHER_SCATTER 1 34 + #define FROM_DPTR 1 35 + 36 + /** 37 + * Enumeration cpt_vf_int_vec_e 38 + * 39 + * CPT VF MSI-X Vector Enumeration 40 + * Enumerates the MSI-X interrupt vectors. 41 + */ 42 + enum cpt_vf_int_vec_e { 43 + CPT_VF_INT_VEC_E_MISC = 0x00, 44 + CPT_VF_INT_VEC_E_DONE = 0x01 45 + }; 46 + 47 + struct command_chunk { 48 + u8 *head; 49 + dma_addr_t dma_addr; 50 + u32 size; /* Chunk size, max CPT_INST_CHUNK_MAX_SIZE */ 51 + struct hlist_node nextchunk; 52 + }; 53 + 54 + struct command_queue { 55 + spinlock_t lock; /* command queue lock */ 56 + u32 idx; /* Command queue host write idx */ 57 + u32 nchunks; /* Number of command chunks */ 58 + struct command_chunk *qhead; /* Command queue head, instructions 59 + * are inserted here 60 + */ 61 + struct hlist_head chead; 62 + }; 63 + 64 + struct command_qinfo { 65 + u32 cmd_size; 66 + u32 qchunksize; /* Command queue chunk size */ 67 + struct command_queue queue[CPT_NUM_QS_PER_VF]; 68 + }; 69 + 70 + struct pending_entry { 71 + u8 busy; /* Entry status (free/busy) */ 72 + 73 + volatile u64 *completion_addr; /* Completion address */ 74 + void *post_arg; 75 + void (*callback)(int, void *); /* Kernel ASYNC request callabck */ 76 + void *callback_arg; /* Kernel ASYNC request callabck arg */ 77 + }; 78 + 79 + struct pending_queue { 80 + struct pending_entry *head; /* head of the queue */ 81 + u32 front; /* Process work from here */ 82 + u32 rear; /* Append new work here */ 83 + atomic64_t pending_count; 84 + spinlock_t lock; /* Queue lock */ 85 + }; 86 + 87 + struct pending_qinfo { 88 + u32 nr_queues; /* Number of queues supported */ 89 + u32 qlen; /* Queue length */ 90 + struct pending_queue queue[CPT_NUM_QS_PER_VF]; 91 + }; 92 + 93 + #define for_each_pending_queue(qinfo, q, i) \ 94 + for (i = 0, q = &qinfo->queue[i]; i < qinfo->nr_queues; i++, \ 95 + q = &qinfo->queue[i]) 96 + 97 + struct cpt_vf { 98 + u16 flags; /* Flags to hold device status bits */ 99 + u8 vfid; /* Device Index 0...CPT_MAX_VF_NUM */ 100 + u8 vftype; /* VF type of SE_TYPE(1) or AE_TYPE(1) */ 101 + u8 vfgrp; /* VF group (0 - 8) */ 102 + u8 node; /* Operating node: Bits (46:44) in BAR0 address */ 103 + u8 priority; /* VF priority ring: 1-High proirity round 104 + * robin ring;0-Low priority round robin ring; 105 + */ 106 + struct pci_dev *pdev; /* pci device handle */ 107 + void __iomem *reg_base; /* Register start address */ 108 + void *wqe_info; /* BH worker info */ 109 + /* MSI-X */ 110 + bool msix_enabled; 111 + struct msix_entry msix_entries[CPT_VF_MSIX_VECTORS]; 112 + bool irq_allocated[CPT_VF_MSIX_VECTORS]; 113 + cpumask_var_t affinity_mask[CPT_VF_MSIX_VECTORS]; 114 + /* Command and Pending queues */ 115 + u32 qsize; 116 + u32 nr_queues; 117 + struct command_qinfo cqinfo; /* Command queue information */ 118 + struct pending_qinfo pqinfo; /* Pending queue information */ 119 + /* VF-PF mailbox communication */ 120 + bool pf_acked; 121 + bool pf_nacked; 122 + }; 123 + 124 + int cptvf_send_vf_up(struct cpt_vf *cptvf); 125 + int cptvf_send_vf_down(struct cpt_vf *cptvf); 126 + int cptvf_send_vf_to_grp_msg(struct cpt_vf *cptvf); 127 + int cptvf_send_vf_priority_msg(struct cpt_vf *cptvf); 128 + int cptvf_send_vq_size_msg(struct cpt_vf *cptvf); 129 + int cptvf_check_pf_ready(struct cpt_vf *cptvf); 130 + void cptvf_handle_mbox_intr(struct cpt_vf *cptvf); 131 + void cvm_crypto_exit(void); 132 + int cvm_crypto_init(struct cpt_vf *cptvf); 133 + void vq_post_process(struct cpt_vf *cptvf, u32 qno); 134 + void cptvf_write_vq_doorbell(struct cpt_vf *cptvf, u32 val); 135 + #endif /* __CPTVF_H */
+444
drivers/crypto/cavium/cpt/cptvf_algs.c
··· 1 + 2 + /* 3 + * Copyright (C) 2016 Cavium, Inc. 4 + * 5 + * This program is free software; you can redistribute it and/or modify it 6 + * under the terms of version 2 of the GNU General Public License 7 + * as published by the Free Software Foundation. 8 + */ 9 + 10 + #include <crypto/aes.h> 11 + #include <crypto/algapi.h> 12 + #include <crypto/authenc.h> 13 + #include <crypto/cryptd.h> 14 + #include <crypto/crypto_wq.h> 15 + #include <crypto/des.h> 16 + #include <crypto/xts.h> 17 + #include <linux/crypto.h> 18 + #include <linux/err.h> 19 + #include <linux/list.h> 20 + #include <linux/scatterlist.h> 21 + 22 + #include "cptvf.h" 23 + #include "cptvf_algs.h" 24 + 25 + struct cpt_device_handle { 26 + void *cdev[MAX_DEVICES]; 27 + u32 dev_count; 28 + }; 29 + 30 + static struct cpt_device_handle dev_handle; 31 + 32 + static void cvm_callback(u32 status, void *arg) 33 + { 34 + struct crypto_async_request *req = (struct crypto_async_request *)arg; 35 + 36 + req->complete(req, !status); 37 + } 38 + 39 + static inline void update_input_iv(struct cpt_request_info *req_info, 40 + u8 *iv, u32 enc_iv_len, 41 + u32 *argcnt) 42 + { 43 + /* Setting the iv information */ 44 + req_info->in[*argcnt].vptr = (void *)iv; 45 + req_info->in[*argcnt].size = enc_iv_len; 46 + req_info->req.dlen += enc_iv_len; 47 + 48 + ++(*argcnt); 49 + } 50 + 51 + static inline void update_output_iv(struct cpt_request_info *req_info, 52 + u8 *iv, u32 enc_iv_len, 53 + u32 *argcnt) 54 + { 55 + /* Setting the iv information */ 56 + req_info->out[*argcnt].vptr = (void *)iv; 57 + req_info->out[*argcnt].size = enc_iv_len; 58 + req_info->rlen += enc_iv_len; 59 + 60 + ++(*argcnt); 61 + } 62 + 63 + static inline void update_input_data(struct cpt_request_info *req_info, 64 + struct scatterlist *inp_sg, 65 + u32 nbytes, u32 *argcnt) 66 + { 67 + req_info->req.dlen += nbytes; 68 + 69 + while (nbytes) { 70 + u32 len = min(nbytes, inp_sg->length); 71 + u8 *ptr = sg_virt(inp_sg); 72 + 73 + req_info->in[*argcnt].vptr = (void *)ptr; 74 + req_info->in[*argcnt].size = len; 75 + nbytes -= len; 76 + 77 + ++(*argcnt); 78 + ++inp_sg; 79 + } 80 + } 81 + 82 + static inline void update_output_data(struct cpt_request_info *req_info, 83 + struct scatterlist *outp_sg, 84 + u32 nbytes, u32 *argcnt) 85 + { 86 + req_info->rlen += nbytes; 87 + 88 + while (nbytes) { 89 + u32 len = min(nbytes, outp_sg->length); 90 + u8 *ptr = sg_virt(outp_sg); 91 + 92 + req_info->out[*argcnt].vptr = (void *)ptr; 93 + req_info->out[*argcnt].size = len; 94 + nbytes -= len; 95 + ++(*argcnt); 96 + ++outp_sg; 97 + } 98 + } 99 + 100 + static inline u32 create_ctx_hdr(struct ablkcipher_request *req, u32 enc, 101 + u32 cipher_type, u32 aes_key_type, 102 + u32 *argcnt) 103 + { 104 + struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); 105 + struct cvm_enc_ctx *ctx = crypto_ablkcipher_ctx(tfm); 106 + struct cvm_req_ctx *rctx = ablkcipher_request_ctx(req); 107 + struct fc_context *fctx = &rctx->fctx; 108 + u64 *offset_control = &rctx->control_word; 109 + u32 enc_iv_len = crypto_ablkcipher_ivsize(tfm); 110 + struct cpt_request_info *req_info = &rctx->cpt_req; 111 + u64 *ctrl_flags = NULL; 112 + 113 + req_info->ctrl.s.grp = 0; 114 + req_info->ctrl.s.dma_mode = DMA_GATHER_SCATTER; 115 + req_info->ctrl.s.se_req = SE_CORE_REQ; 116 + 117 + req_info->req.opcode.s.major = MAJOR_OP_FC | 118 + DMA_MODE_FLAG(DMA_GATHER_SCATTER); 119 + if (enc) 120 + req_info->req.opcode.s.minor = 2; 121 + else 122 + req_info->req.opcode.s.minor = 3; 123 + 124 + req_info->req.param1 = req->nbytes; /* Encryption Data length */ 125 + req_info->req.param2 = 0; /*Auth data length */ 126 + 127 + fctx->enc.enc_ctrl.e.enc_cipher = cipher_type; 128 + fctx->enc.enc_ctrl.e.aes_key = aes_key_type; 129 + fctx->enc.enc_ctrl.e.iv_source = FROM_DPTR; 130 + 131 + if (cipher_type == AES_XTS) 132 + memcpy(fctx->enc.encr_key, ctx->enc_key, ctx->key_len * 2); 133 + else 134 + memcpy(fctx->enc.encr_key, ctx->enc_key, ctx->key_len); 135 + ctrl_flags = (u64 *)&fctx->enc.enc_ctrl.flags; 136 + *ctrl_flags = cpu_to_be64(*ctrl_flags); 137 + 138 + *offset_control = cpu_to_be64(((u64)(enc_iv_len) << 16)); 139 + /* Storing Packet Data Information in offset 140 + * Control Word First 8 bytes 141 + */ 142 + req_info->in[*argcnt].vptr = (u8 *)offset_control; 143 + req_info->in[*argcnt].size = CONTROL_WORD_LEN; 144 + req_info->req.dlen += CONTROL_WORD_LEN; 145 + ++(*argcnt); 146 + 147 + req_info->in[*argcnt].vptr = (u8 *)fctx; 148 + req_info->in[*argcnt].size = sizeof(struct fc_context); 149 + req_info->req.dlen += sizeof(struct fc_context); 150 + 151 + ++(*argcnt); 152 + 153 + return 0; 154 + } 155 + 156 + static inline u32 create_input_list(struct ablkcipher_request *req, u32 enc, 157 + u32 cipher_type, u32 aes_key_type, 158 + u32 enc_iv_len) 159 + { 160 + struct cvm_req_ctx *rctx = ablkcipher_request_ctx(req); 161 + struct cpt_request_info *req_info = &rctx->cpt_req; 162 + u32 argcnt = 0; 163 + 164 + create_ctx_hdr(req, enc, cipher_type, aes_key_type, &argcnt); 165 + update_input_iv(req_info, req->info, enc_iv_len, &argcnt); 166 + update_input_data(req_info, req->src, req->nbytes, &argcnt); 167 + req_info->incnt = argcnt; 168 + 169 + return 0; 170 + } 171 + 172 + static inline void store_cb_info(struct ablkcipher_request *req, 173 + struct cpt_request_info *req_info) 174 + { 175 + req_info->callback = (void *)cvm_callback; 176 + req_info->callback_arg = (void *)&req->base; 177 + } 178 + 179 + static inline void create_output_list(struct ablkcipher_request *req, 180 + u32 cipher_type, 181 + u32 enc_iv_len) 182 + { 183 + struct cvm_req_ctx *rctx = ablkcipher_request_ctx(req); 184 + struct cpt_request_info *req_info = &rctx->cpt_req; 185 + u32 argcnt = 0; 186 + 187 + /* OUTPUT Buffer Processing 188 + * AES encryption/decryption output would be 189 + * received in the following format 190 + * 191 + * ------IV--------|------ENCRYPTED/DECRYPTED DATA-----| 192 + * [ 16 Bytes/ [ Request Enc/Dec/ DATA Len AES CBC ] 193 + */ 194 + /* Reading IV information */ 195 + update_output_iv(req_info, req->info, enc_iv_len, &argcnt); 196 + update_output_data(req_info, req->dst, req->nbytes, &argcnt); 197 + req_info->outcnt = argcnt; 198 + } 199 + 200 + static inline int cvm_enc_dec(struct ablkcipher_request *req, u32 enc, 201 + u32 cipher_type) 202 + { 203 + struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); 204 + struct cvm_enc_ctx *ctx = crypto_ablkcipher_ctx(tfm); 205 + u32 key_type = AES_128_BIT; 206 + struct cvm_req_ctx *rctx = ablkcipher_request_ctx(req); 207 + u32 enc_iv_len = crypto_ablkcipher_ivsize(tfm); 208 + struct fc_context *fctx = &rctx->fctx; 209 + struct cpt_request_info *req_info = &rctx->cpt_req; 210 + void *cdev = NULL; 211 + int status; 212 + 213 + switch (ctx->key_len) { 214 + case 16: 215 + key_type = AES_128_BIT; 216 + break; 217 + case 24: 218 + key_type = AES_192_BIT; 219 + break; 220 + case 32: 221 + if (cipher_type == AES_XTS) 222 + key_type = AES_128_BIT; 223 + else 224 + key_type = AES_256_BIT; 225 + break; 226 + case 64: 227 + if (cipher_type == AES_XTS) 228 + key_type = AES_256_BIT; 229 + else 230 + return -EINVAL; 231 + break; 232 + default: 233 + return -EINVAL; 234 + } 235 + 236 + if (cipher_type == DES3_CBC) 237 + key_type = 0; 238 + 239 + memset(req_info, 0, sizeof(struct cpt_request_info)); 240 + memset(fctx, 0, sizeof(struct fc_context)); 241 + create_input_list(req, enc, cipher_type, key_type, enc_iv_len); 242 + create_output_list(req, cipher_type, enc_iv_len); 243 + store_cb_info(req, req_info); 244 + cdev = dev_handle.cdev[smp_processor_id()]; 245 + status = cptvf_do_request(cdev, req_info); 246 + /* We perform an asynchronous send and once 247 + * the request is completed the driver would 248 + * intimate through registered call back functions 249 + */ 250 + 251 + if (status) 252 + return status; 253 + else 254 + return -EINPROGRESS; 255 + } 256 + 257 + int cvm_des3_encrypt_cbc(struct ablkcipher_request *req) 258 + { 259 + return cvm_enc_dec(req, true, DES3_CBC); 260 + } 261 + 262 + int cvm_des3_decrypt_cbc(struct ablkcipher_request *req) 263 + { 264 + return cvm_enc_dec(req, false, DES3_CBC); 265 + } 266 + 267 + int cvm_aes_encrypt_xts(struct ablkcipher_request *req) 268 + { 269 + return cvm_enc_dec(req, true, AES_XTS); 270 + } 271 + 272 + int cvm_aes_decrypt_xts(struct ablkcipher_request *req) 273 + { 274 + return cvm_enc_dec(req, false, AES_XTS); 275 + } 276 + 277 + int cvm_aes_encrypt_cbc(struct ablkcipher_request *req) 278 + { 279 + return cvm_enc_dec(req, true, AES_CBC); 280 + } 281 + 282 + int cvm_aes_decrypt_cbc(struct ablkcipher_request *req) 283 + { 284 + return cvm_enc_dec(req, false, AES_CBC); 285 + } 286 + 287 + int cvm_xts_setkey(struct crypto_ablkcipher *cipher, const u8 *key, 288 + u32 keylen) 289 + { 290 + struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher); 291 + struct cvm_enc_ctx *ctx = crypto_tfm_ctx(tfm); 292 + int err; 293 + const u8 *key1 = key; 294 + const u8 *key2 = key + (keylen / 2); 295 + 296 + err = xts_check_key(tfm, key, keylen); 297 + if (err) 298 + return err; 299 + ctx->key_len = keylen; 300 + memcpy(ctx->enc_key, key1, keylen / 2); 301 + memcpy(ctx->enc_key + KEY2_OFFSET, key2, keylen / 2); 302 + 303 + return 0; 304 + } 305 + 306 + int cvm_enc_dec_setkey(struct crypto_ablkcipher *cipher, const u8 *key, 307 + u32 keylen) 308 + { 309 + struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher); 310 + struct cvm_enc_ctx *ctx = crypto_tfm_ctx(tfm); 311 + 312 + if ((keylen == 16) || (keylen == 24) || (keylen == 32)) { 313 + ctx->key_len = keylen; 314 + memcpy(ctx->enc_key, key, keylen); 315 + return 0; 316 + } 317 + crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN); 318 + 319 + return -EINVAL; 320 + } 321 + 322 + int cvm_enc_dec_init(struct crypto_tfm *tfm) 323 + { 324 + struct cvm_enc_ctx *ctx = crypto_tfm_ctx(tfm); 325 + 326 + memset(ctx, 0, sizeof(*ctx)); 327 + tfm->crt_ablkcipher.reqsize = sizeof(struct cvm_req_ctx) + 328 + sizeof(struct ablkcipher_request); 329 + /* Additional memory for ablkcipher_request is 330 + * allocated since the cryptd daemon uses 331 + * this memory for request_ctx information 332 + */ 333 + 334 + return 0; 335 + } 336 + 337 + struct crypto_alg algs[] = { { 338 + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, 339 + .cra_blocksize = AES_BLOCK_SIZE, 340 + .cra_ctxsize = sizeof(struct cvm_enc_ctx), 341 + .cra_alignmask = 7, 342 + .cra_priority = 4001, 343 + .cra_name = "xts(aes)", 344 + .cra_driver_name = "cavium-xts-aes", 345 + .cra_type = &crypto_ablkcipher_type, 346 + .cra_u = { 347 + .ablkcipher = { 348 + .ivsize = AES_BLOCK_SIZE, 349 + .min_keysize = 2 * AES_MIN_KEY_SIZE, 350 + .max_keysize = 2 * AES_MAX_KEY_SIZE, 351 + .setkey = cvm_xts_setkey, 352 + .encrypt = cvm_aes_encrypt_xts, 353 + .decrypt = cvm_aes_decrypt_xts, 354 + }, 355 + }, 356 + .cra_init = cvm_enc_dec_init, 357 + .cra_module = THIS_MODULE, 358 + }, { 359 + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, 360 + .cra_blocksize = AES_BLOCK_SIZE, 361 + .cra_ctxsize = sizeof(struct cvm_enc_ctx), 362 + .cra_alignmask = 7, 363 + .cra_priority = 4001, 364 + .cra_name = "cbc(aes)", 365 + .cra_driver_name = "cavium-cbc-aes", 366 + .cra_type = &crypto_ablkcipher_type, 367 + .cra_u = { 368 + .ablkcipher = { 369 + .ivsize = AES_BLOCK_SIZE, 370 + .min_keysize = AES_MIN_KEY_SIZE, 371 + .max_keysize = AES_MAX_KEY_SIZE, 372 + .setkey = cvm_enc_dec_setkey, 373 + .encrypt = cvm_aes_encrypt_cbc, 374 + .decrypt = cvm_aes_decrypt_cbc, 375 + }, 376 + }, 377 + .cra_init = cvm_enc_dec_init, 378 + .cra_module = THIS_MODULE, 379 + }, { 380 + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, 381 + .cra_blocksize = DES3_EDE_BLOCK_SIZE, 382 + .cra_ctxsize = sizeof(struct cvm_des3_ctx), 383 + .cra_alignmask = 7, 384 + .cra_priority = 4001, 385 + .cra_name = "cbc(des3_ede)", 386 + .cra_driver_name = "cavium-cbc-des3_ede", 387 + .cra_type = &crypto_ablkcipher_type, 388 + .cra_u = { 389 + .ablkcipher = { 390 + .min_keysize = DES3_EDE_KEY_SIZE, 391 + .max_keysize = DES3_EDE_KEY_SIZE, 392 + .ivsize = DES_BLOCK_SIZE, 393 + .setkey = cvm_enc_dec_setkey, 394 + .encrypt = cvm_des3_encrypt_cbc, 395 + .decrypt = cvm_des3_decrypt_cbc, 396 + }, 397 + }, 398 + .cra_init = cvm_enc_dec_init, 399 + .cra_module = THIS_MODULE, 400 + } }; 401 + 402 + static inline int cav_register_algs(void) 403 + { 404 + int err = 0; 405 + 406 + err = crypto_register_algs(algs, ARRAY_SIZE(algs)); 407 + if (err) 408 + return err; 409 + 410 + return 0; 411 + } 412 + 413 + static inline void cav_unregister_algs(void) 414 + { 415 + crypto_unregister_algs(algs, ARRAY_SIZE(algs)); 416 + } 417 + 418 + int cvm_crypto_init(struct cpt_vf *cptvf) 419 + { 420 + struct pci_dev *pdev = cptvf->pdev; 421 + u32 dev_count; 422 + 423 + dev_count = dev_handle.dev_count; 424 + dev_handle.cdev[dev_count] = cptvf; 425 + dev_handle.dev_count++; 426 + 427 + if (dev_count == 3) { 428 + if (cav_register_algs()) { 429 + dev_err(&pdev->dev, "Error in registering crypto algorithms\n"); 430 + return -EINVAL; 431 + } 432 + } 433 + 434 + return 0; 435 + } 436 + 437 + void cvm_crypto_exit(void) 438 + { 439 + u32 dev_count; 440 + 441 + dev_count = --dev_handle.dev_count; 442 + if (!dev_count) 443 + cav_unregister_algs(); 444 + }
+113
drivers/crypto/cavium/cpt/cptvf_algs.h
··· 1 + /* 2 + * Copyright (C) 2016 Cavium, Inc. 3 + * 4 + * This program is free software; you can redistribute it and/or modify it 5 + * under the terms of version 2 of the GNU General Public License 6 + * as published by the Free Software Foundation. 7 + */ 8 + 9 + #ifndef _CPTVF_ALGS_H_ 10 + #define _CPTVF_ALGS_H_ 11 + 12 + #include "request_manager.h" 13 + 14 + #define MAX_DEVICES 16 15 + #define MAJOR_OP_FC 0x33 16 + #define MAX_ENC_KEY_SIZE 32 17 + #define MAX_HASH_KEY_SIZE 64 18 + #define MAX_KEY_SIZE (MAX_ENC_KEY_SIZE + MAX_HASH_KEY_SIZE) 19 + #define CONTROL_WORD_LEN 8 20 + #define KEY2_OFFSET 48 21 + 22 + #define DMA_MODE_FLAG(dma_mode) \ 23 + (((dma_mode) == DMA_GATHER_SCATTER) ? (1 << 7) : 0) 24 + 25 + enum req_type { 26 + AE_CORE_REQ, 27 + SE_CORE_REQ, 28 + }; 29 + 30 + enum cipher_type { 31 + DES3_CBC = 0x1, 32 + DES3_ECB = 0x2, 33 + AES_CBC = 0x3, 34 + AES_ECB = 0x4, 35 + AES_CFB = 0x5, 36 + AES_CTR = 0x6, 37 + AES_GCM = 0x7, 38 + AES_XTS = 0x8 39 + }; 40 + 41 + enum aes_type { 42 + AES_128_BIT = 0x1, 43 + AES_192_BIT = 0x2, 44 + AES_256_BIT = 0x3 45 + }; 46 + 47 + union encr_ctrl { 48 + u64 flags; 49 + struct { 50 + #if defined(__BIG_ENDIAN_BITFIELD) 51 + u64 enc_cipher:4; 52 + u64 reserved1:1; 53 + u64 aes_key:2; 54 + u64 iv_source:1; 55 + u64 hash_type:4; 56 + u64 reserved2:3; 57 + u64 auth_input_type:1; 58 + u64 mac_len:8; 59 + u64 reserved3:8; 60 + u64 encr_offset:16; 61 + u64 iv_offset:8; 62 + u64 auth_offset:8; 63 + #else 64 + u64 auth_offset:8; 65 + u64 iv_offset:8; 66 + u64 encr_offset:16; 67 + u64 reserved3:8; 68 + u64 mac_len:8; 69 + u64 auth_input_type:1; 70 + u64 reserved2:3; 71 + u64 hash_type:4; 72 + u64 iv_source:1; 73 + u64 aes_key:2; 74 + u64 reserved1:1; 75 + u64 enc_cipher:4; 76 + #endif 77 + } e; 78 + }; 79 + 80 + struct enc_context { 81 + union encr_ctrl enc_ctrl; 82 + u8 encr_key[32]; 83 + u8 encr_iv[16]; 84 + }; 85 + 86 + struct fchmac_context { 87 + u8 ipad[64]; 88 + u8 opad[64]; /* or OPAD */ 89 + }; 90 + 91 + struct fc_context { 92 + struct enc_context enc; 93 + struct fchmac_context hmac; 94 + }; 95 + 96 + struct cvm_enc_ctx { 97 + u32 key_len; 98 + u8 enc_key[MAX_KEY_SIZE]; 99 + }; 100 + 101 + struct cvm_des3_ctx { 102 + u32 key_len; 103 + u8 des3_key[MAX_KEY_SIZE]; 104 + }; 105 + 106 + struct cvm_req_ctx { 107 + struct cpt_request_info cpt_req; 108 + u64 control_word; 109 + struct fc_context fctx; 110 + }; 111 + 112 + int cptvf_do_request(void *cptvf, struct cpt_request_info *req); 113 + #endif /*_CPTVF_ALGS_H_*/
+936
drivers/crypto/cavium/cpt/cptvf_main.c
··· 1 + /* 2 + * Copyright (C) 2016 Cavium, Inc. 3 + * 4 + * This program is free software; you can redistribute it and/or modify 5 + * it under the terms of version 2 of the GNU General Public License 6 + * as published by the Free Software Foundation. 7 + */ 8 + 9 + #include <linux/interrupt.h> 10 + #include <linux/module.h> 11 + 12 + #include "cptvf.h" 13 + 14 + #define DRV_NAME "thunder-cptvf" 15 + #define DRV_VERSION "1.0" 16 + 17 + struct cptvf_wqe { 18 + struct tasklet_struct twork; 19 + void *cptvf; 20 + u32 qno; 21 + }; 22 + 23 + struct cptvf_wqe_info { 24 + struct cptvf_wqe vq_wqe[CPT_NUM_QS_PER_VF]; 25 + }; 26 + 27 + static void vq_work_handler(unsigned long data) 28 + { 29 + struct cptvf_wqe_info *cwqe_info = (struct cptvf_wqe_info *)data; 30 + struct cptvf_wqe *cwqe = &cwqe_info->vq_wqe[0]; 31 + 32 + vq_post_process(cwqe->cptvf, cwqe->qno); 33 + } 34 + 35 + static int init_worker_threads(struct cpt_vf *cptvf) 36 + { 37 + struct pci_dev *pdev = cptvf->pdev; 38 + struct cptvf_wqe_info *cwqe_info; 39 + int i; 40 + 41 + cwqe_info = kzalloc(sizeof(*cwqe_info), GFP_KERNEL); 42 + if (!cwqe_info) 43 + return -ENOMEM; 44 + 45 + if (cptvf->nr_queues) { 46 + dev_info(&pdev->dev, "Creating VQ worker threads (%d)\n", 47 + cptvf->nr_queues); 48 + } 49 + 50 + for (i = 0; i < cptvf->nr_queues; i++) { 51 + tasklet_init(&cwqe_info->vq_wqe[i].twork, vq_work_handler, 52 + (u64)cwqe_info); 53 + cwqe_info->vq_wqe[i].qno = i; 54 + cwqe_info->vq_wqe[i].cptvf = cptvf; 55 + } 56 + 57 + cptvf->wqe_info = cwqe_info; 58 + 59 + return 0; 60 + } 61 + 62 + static void cleanup_worker_threads(struct cpt_vf *cptvf) 63 + { 64 + struct cptvf_wqe_info *cwqe_info; 65 + struct pci_dev *pdev = cptvf->pdev; 66 + int i; 67 + 68 + cwqe_info = (struct cptvf_wqe_info *)cptvf->wqe_info; 69 + if (!cwqe_info) 70 + return; 71 + 72 + if (cptvf->nr_queues) { 73 + dev_info(&pdev->dev, "Cleaning VQ worker threads (%u)\n", 74 + cptvf->nr_queues); 75 + } 76 + 77 + for (i = 0; i < cptvf->nr_queues; i++) 78 + tasklet_kill(&cwqe_info->vq_wqe[i].twork); 79 + 80 + kzfree(cwqe_info); 81 + cptvf->wqe_info = NULL; 82 + } 83 + 84 + static void free_pending_queues(struct pending_qinfo *pqinfo) 85 + { 86 + int i; 87 + struct pending_queue *queue; 88 + 89 + for_each_pending_queue(pqinfo, queue, i) { 90 + if (!queue->head) 91 + continue; 92 + 93 + /* free single queue */ 94 + kzfree((queue->head)); 95 + 96 + queue->front = 0; 97 + queue->rear = 0; 98 + 99 + return; 100 + } 101 + 102 + pqinfo->qlen = 0; 103 + pqinfo->nr_queues = 0; 104 + } 105 + 106 + static int alloc_pending_queues(struct pending_qinfo *pqinfo, u32 qlen, 107 + u32 nr_queues) 108 + { 109 + u32 i; 110 + size_t size; 111 + int ret; 112 + struct pending_queue *queue = NULL; 113 + 114 + pqinfo->nr_queues = nr_queues; 115 + pqinfo->qlen = qlen; 116 + 117 + size = (qlen * sizeof(struct pending_entry)); 118 + 119 + for_each_pending_queue(pqinfo, queue, i) { 120 + queue->head = kzalloc((size), GFP_KERNEL); 121 + if (!queue->head) { 122 + ret = -ENOMEM; 123 + goto pending_qfail; 124 + } 125 + 126 + queue->front = 0; 127 + queue->rear = 0; 128 + atomic64_set((&queue->pending_count), (0)); 129 + 130 + /* init queue spin lock */ 131 + spin_lock_init(&queue->lock); 132 + } 133 + 134 + return 0; 135 + 136 + pending_qfail: 137 + free_pending_queues(pqinfo); 138 + 139 + return ret; 140 + } 141 + 142 + static int init_pending_queues(struct cpt_vf *cptvf, u32 qlen, u32 nr_queues) 143 + { 144 + struct pci_dev *pdev = cptvf->pdev; 145 + int ret; 146 + 147 + if (!nr_queues) 148 + return 0; 149 + 150 + ret = alloc_pending_queues(&cptvf->pqinfo, qlen, nr_queues); 151 + if (ret) { 152 + dev_err(&pdev->dev, "failed to setup pending queues (%u)\n", 153 + nr_queues); 154 + return ret; 155 + } 156 + 157 + return 0; 158 + } 159 + 160 + static void cleanup_pending_queues(struct cpt_vf *cptvf) 161 + { 162 + struct pci_dev *pdev = cptvf->pdev; 163 + 164 + if (!cptvf->nr_queues) 165 + return; 166 + 167 + dev_info(&pdev->dev, "Cleaning VQ pending queue (%u)\n", 168 + cptvf->nr_queues); 169 + free_pending_queues(&cptvf->pqinfo); 170 + } 171 + 172 + static void free_command_queues(struct cpt_vf *cptvf, 173 + struct command_qinfo *cqinfo) 174 + { 175 + int i; 176 + struct command_queue *queue = NULL; 177 + struct command_chunk *chunk = NULL; 178 + struct pci_dev *pdev = cptvf->pdev; 179 + struct hlist_node *node; 180 + 181 + /* clean up for each queue */ 182 + for (i = 0; i < cptvf->nr_queues; i++) { 183 + queue = &cqinfo->queue[i]; 184 + if (hlist_empty(&cqinfo->queue[i].chead)) 185 + continue; 186 + 187 + hlist_for_each_entry_safe(chunk, node, &cqinfo->queue[i].chead, 188 + nextchunk) { 189 + dma_free_coherent(&pdev->dev, chunk->size, 190 + chunk->head, 191 + chunk->dma_addr); 192 + chunk->head = NULL; 193 + chunk->dma_addr = 0; 194 + hlist_del(&chunk->nextchunk); 195 + kzfree(chunk); 196 + } 197 + 198 + queue->nchunks = 0; 199 + queue->idx = 0; 200 + } 201 + 202 + /* common cleanup */ 203 + cqinfo->cmd_size = 0; 204 + } 205 + 206 + static int alloc_command_queues(struct cpt_vf *cptvf, 207 + struct command_qinfo *cqinfo, size_t cmd_size, 208 + u32 qlen) 209 + { 210 + int i; 211 + size_t q_size; 212 + struct command_queue *queue = NULL; 213 + struct pci_dev *pdev = cptvf->pdev; 214 + 215 + /* common init */ 216 + cqinfo->cmd_size = cmd_size; 217 + /* Qsize in dwords, needed for SADDR config, 1-next chunk pointer */ 218 + cptvf->qsize = min(qlen, cqinfo->qchunksize) * 219 + CPT_NEXT_CHUNK_PTR_SIZE + 1; 220 + /* Qsize in bytes to create space for alignment */ 221 + q_size = qlen * cqinfo->cmd_size; 222 + 223 + /* per queue initialization */ 224 + for (i = 0; i < cptvf->nr_queues; i++) { 225 + size_t c_size = 0; 226 + size_t rem_q_size = q_size; 227 + struct command_chunk *curr = NULL, *first = NULL, *last = NULL; 228 + u32 qcsize_bytes = cqinfo->qchunksize * cqinfo->cmd_size; 229 + 230 + queue = &cqinfo->queue[i]; 231 + INIT_HLIST_HEAD(&cqinfo->queue[i].chead); 232 + do { 233 + curr = kzalloc(sizeof(*curr), GFP_KERNEL); 234 + if (!curr) 235 + goto cmd_qfail; 236 + 237 + c_size = (rem_q_size > qcsize_bytes) ? qcsize_bytes : 238 + rem_q_size; 239 + curr->head = (u8 *)dma_zalloc_coherent(&pdev->dev, 240 + c_size + CPT_NEXT_CHUNK_PTR_SIZE, 241 + &curr->dma_addr, GFP_KERNEL); 242 + if (!curr->head) { 243 + dev_err(&pdev->dev, "Command Q (%d) chunk (%d) allocation failed\n", 244 + i, queue->nchunks); 245 + goto cmd_qfail; 246 + } 247 + 248 + curr->size = c_size; 249 + if (queue->nchunks == 0) { 250 + hlist_add_head(&curr->nextchunk, 251 + &cqinfo->queue[i].chead); 252 + first = curr; 253 + } else { 254 + hlist_add_behind(&curr->nextchunk, 255 + &last->nextchunk); 256 + } 257 + 258 + queue->nchunks++; 259 + rem_q_size -= c_size; 260 + if (last) 261 + *((u64 *)(&last->head[last->size])) = (u64)curr->dma_addr; 262 + 263 + last = curr; 264 + } while (rem_q_size); 265 + 266 + /* Make the queue circular */ 267 + /* Tie back last chunk entry to head */ 268 + curr = first; 269 + *((u64 *)(&last->head[last->size])) = (u64)curr->dma_addr; 270 + queue->qhead = curr; 271 + spin_lock_init(&queue->lock); 272 + } 273 + return 0; 274 + 275 + cmd_qfail: 276 + free_command_queues(cptvf, cqinfo); 277 + return -ENOMEM; 278 + } 279 + 280 + static int init_command_queues(struct cpt_vf *cptvf, u32 qlen) 281 + { 282 + struct pci_dev *pdev = cptvf->pdev; 283 + int ret; 284 + 285 + /* setup AE command queues */ 286 + ret = alloc_command_queues(cptvf, &cptvf->cqinfo, CPT_INST_SIZE, 287 + qlen); 288 + if (ret) { 289 + dev_err(&pdev->dev, "failed to allocate AE command queues (%u)\n", 290 + cptvf->nr_queues); 291 + return ret; 292 + } 293 + 294 + return ret; 295 + } 296 + 297 + static void cleanup_command_queues(struct cpt_vf *cptvf) 298 + { 299 + struct pci_dev *pdev = cptvf->pdev; 300 + 301 + if (!cptvf->nr_queues) 302 + return; 303 + 304 + dev_info(&pdev->dev, "Cleaning VQ command queue (%u)\n", 305 + cptvf->nr_queues); 306 + free_command_queues(cptvf, &cptvf->cqinfo); 307 + } 308 + 309 + static void cptvf_sw_cleanup(struct cpt_vf *cptvf) 310 + { 311 + cleanup_worker_threads(cptvf); 312 + cleanup_pending_queues(cptvf); 313 + cleanup_command_queues(cptvf); 314 + } 315 + 316 + static int cptvf_sw_init(struct cpt_vf *cptvf, u32 qlen, u32 nr_queues) 317 + { 318 + struct pci_dev *pdev = cptvf->pdev; 319 + int ret = 0; 320 + u32 max_dev_queues = 0; 321 + 322 + max_dev_queues = CPT_NUM_QS_PER_VF; 323 + /* possible cpus */ 324 + nr_queues = min_t(u32, nr_queues, max_dev_queues); 325 + cptvf->nr_queues = nr_queues; 326 + 327 + ret = init_command_queues(cptvf, qlen); 328 + if (ret) { 329 + dev_err(&pdev->dev, "Failed to setup command queues (%u)\n", 330 + nr_queues); 331 + return ret; 332 + } 333 + 334 + ret = init_pending_queues(cptvf, qlen, nr_queues); 335 + if (ret) { 336 + dev_err(&pdev->dev, "Failed to setup pending queues (%u)\n", 337 + nr_queues); 338 + goto setup_pqfail; 339 + } 340 + 341 + /* Create worker threads for BH processing */ 342 + ret = init_worker_threads(cptvf); 343 + if (ret) { 344 + dev_err(&pdev->dev, "Failed to setup worker threads\n"); 345 + goto init_work_fail; 346 + } 347 + 348 + return 0; 349 + 350 + init_work_fail: 351 + cleanup_worker_threads(cptvf); 352 + cleanup_pending_queues(cptvf); 353 + 354 + setup_pqfail: 355 + cleanup_command_queues(cptvf); 356 + 357 + return ret; 358 + } 359 + 360 + static void cptvf_disable_msix(struct cpt_vf *cptvf) 361 + { 362 + if (cptvf->msix_enabled) { 363 + pci_disable_msix(cptvf->pdev); 364 + cptvf->msix_enabled = 0; 365 + } 366 + } 367 + 368 + static int cptvf_enable_msix(struct cpt_vf *cptvf) 369 + { 370 + int i, ret; 371 + 372 + for (i = 0; i < CPT_VF_MSIX_VECTORS; i++) 373 + cptvf->msix_entries[i].entry = i; 374 + 375 + ret = pci_enable_msix(cptvf->pdev, cptvf->msix_entries, 376 + CPT_VF_MSIX_VECTORS); 377 + if (ret) { 378 + dev_err(&cptvf->pdev->dev, "Request for #%d msix vectors failed\n", 379 + CPT_VF_MSIX_VECTORS); 380 + return ret; 381 + } 382 + 383 + cptvf->msix_enabled = 1; 384 + /* Mark MSIX enabled */ 385 + cptvf->flags |= CPT_FLAG_MSIX_ENABLED; 386 + 387 + return 0; 388 + } 389 + 390 + static void cptvf_free_all_interrupts(struct cpt_vf *cptvf) 391 + { 392 + int irq; 393 + 394 + for (irq = 0; irq < CPT_VF_MSIX_VECTORS; irq++) { 395 + if (cptvf->irq_allocated[irq]) 396 + irq_set_affinity_hint(cptvf->msix_entries[irq].vector, 397 + NULL); 398 + free_cpumask_var(cptvf->affinity_mask[irq]); 399 + free_irq(cptvf->msix_entries[irq].vector, cptvf); 400 + cptvf->irq_allocated[irq] = false; 401 + } 402 + } 403 + 404 + static void cptvf_write_vq_ctl(struct cpt_vf *cptvf, bool val) 405 + { 406 + union cptx_vqx_ctl vqx_ctl; 407 + 408 + vqx_ctl.u = cpt_read_csr64(cptvf->reg_base, CPTX_VQX_CTL(0, 0)); 409 + vqx_ctl.s.ena = val; 410 + cpt_write_csr64(cptvf->reg_base, CPTX_VQX_CTL(0, 0), vqx_ctl.u); 411 + } 412 + 413 + void cptvf_write_vq_doorbell(struct cpt_vf *cptvf, u32 val) 414 + { 415 + union cptx_vqx_doorbell vqx_dbell; 416 + 417 + vqx_dbell.u = cpt_read_csr64(cptvf->reg_base, 418 + CPTX_VQX_DOORBELL(0, 0)); 419 + vqx_dbell.s.dbell_cnt = val * 8; /* Num of Instructions * 8 words */ 420 + cpt_write_csr64(cptvf->reg_base, CPTX_VQX_DOORBELL(0, 0), 421 + vqx_dbell.u); 422 + } 423 + 424 + static void cptvf_write_vq_inprog(struct cpt_vf *cptvf, u8 val) 425 + { 426 + union cptx_vqx_inprog vqx_inprg; 427 + 428 + vqx_inprg.u = cpt_read_csr64(cptvf->reg_base, CPTX_VQX_INPROG(0, 0)); 429 + vqx_inprg.s.inflight = val; 430 + cpt_write_csr64(cptvf->reg_base, CPTX_VQX_INPROG(0, 0), vqx_inprg.u); 431 + } 432 + 433 + static void cptvf_write_vq_done_numwait(struct cpt_vf *cptvf, u32 val) 434 + { 435 + union cptx_vqx_done_wait vqx_dwait; 436 + 437 + vqx_dwait.u = cpt_read_csr64(cptvf->reg_base, 438 + CPTX_VQX_DONE_WAIT(0, 0)); 439 + vqx_dwait.s.num_wait = val; 440 + cpt_write_csr64(cptvf->reg_base, CPTX_VQX_DONE_WAIT(0, 0), 441 + vqx_dwait.u); 442 + } 443 + 444 + static void cptvf_write_vq_done_timewait(struct cpt_vf *cptvf, u16 time) 445 + { 446 + union cptx_vqx_done_wait vqx_dwait; 447 + 448 + vqx_dwait.u = cpt_read_csr64(cptvf->reg_base, 449 + CPTX_VQX_DONE_WAIT(0, 0)); 450 + vqx_dwait.s.time_wait = time; 451 + cpt_write_csr64(cptvf->reg_base, CPTX_VQX_DONE_WAIT(0, 0), 452 + vqx_dwait.u); 453 + } 454 + 455 + static void cptvf_enable_swerr_interrupts(struct cpt_vf *cptvf) 456 + { 457 + union cptx_vqx_misc_ena_w1s vqx_misc_ena; 458 + 459 + vqx_misc_ena.u = cpt_read_csr64(cptvf->reg_base, 460 + CPTX_VQX_MISC_ENA_W1S(0, 0)); 461 + /* Set mbox(0) interupts for the requested vf */ 462 + vqx_misc_ena.s.swerr = 1; 463 + cpt_write_csr64(cptvf->reg_base, CPTX_VQX_MISC_ENA_W1S(0, 0), 464 + vqx_misc_ena.u); 465 + } 466 + 467 + static void cptvf_enable_mbox_interrupts(struct cpt_vf *cptvf) 468 + { 469 + union cptx_vqx_misc_ena_w1s vqx_misc_ena; 470 + 471 + vqx_misc_ena.u = cpt_read_csr64(cptvf->reg_base, 472 + CPTX_VQX_MISC_ENA_W1S(0, 0)); 473 + /* Set mbox(0) interupts for the requested vf */ 474 + vqx_misc_ena.s.mbox = 1; 475 + cpt_write_csr64(cptvf->reg_base, CPTX_VQX_MISC_ENA_W1S(0, 0), 476 + vqx_misc_ena.u); 477 + } 478 + 479 + static void cptvf_enable_done_interrupts(struct cpt_vf *cptvf) 480 + { 481 + union cptx_vqx_done_ena_w1s vqx_done_ena; 482 + 483 + vqx_done_ena.u = cpt_read_csr64(cptvf->reg_base, 484 + CPTX_VQX_DONE_ENA_W1S(0, 0)); 485 + /* Set DONE interrupt for the requested vf */ 486 + vqx_done_ena.s.done = 1; 487 + cpt_write_csr64(cptvf->reg_base, CPTX_VQX_DONE_ENA_W1S(0, 0), 488 + vqx_done_ena.u); 489 + } 490 + 491 + static void cptvf_clear_dovf_intr(struct cpt_vf *cptvf) 492 + { 493 + union cptx_vqx_misc_int vqx_misc_int; 494 + 495 + vqx_misc_int.u = cpt_read_csr64(cptvf->reg_base, 496 + CPTX_VQX_MISC_INT(0, 0)); 497 + /* W1C for the VF */ 498 + vqx_misc_int.s.dovf = 1; 499 + cpt_write_csr64(cptvf->reg_base, CPTX_VQX_MISC_INT(0, 0), 500 + vqx_misc_int.u); 501 + } 502 + 503 + static void cptvf_clear_irde_intr(struct cpt_vf *cptvf) 504 + { 505 + union cptx_vqx_misc_int vqx_misc_int; 506 + 507 + vqx_misc_int.u = cpt_read_csr64(cptvf->reg_base, 508 + CPTX_VQX_MISC_INT(0, 0)); 509 + /* W1C for the VF */ 510 + vqx_misc_int.s.irde = 1; 511 + cpt_write_csr64(cptvf->reg_base, CPTX_VQX_MISC_INT(0, 0), 512 + vqx_misc_int.u); 513 + } 514 + 515 + static void cptvf_clear_nwrp_intr(struct cpt_vf *cptvf) 516 + { 517 + union cptx_vqx_misc_int vqx_misc_int; 518 + 519 + vqx_misc_int.u = cpt_read_csr64(cptvf->reg_base, 520 + CPTX_VQX_MISC_INT(0, 0)); 521 + /* W1C for the VF */ 522 + vqx_misc_int.s.nwrp = 1; 523 + cpt_write_csr64(cptvf->reg_base, 524 + CPTX_VQX_MISC_INT(0, 0), vqx_misc_int.u); 525 + } 526 + 527 + static void cptvf_clear_mbox_intr(struct cpt_vf *cptvf) 528 + { 529 + union cptx_vqx_misc_int vqx_misc_int; 530 + 531 + vqx_misc_int.u = cpt_read_csr64(cptvf->reg_base, 532 + CPTX_VQX_MISC_INT(0, 0)); 533 + /* W1C for the VF */ 534 + vqx_misc_int.s.mbox = 1; 535 + cpt_write_csr64(cptvf->reg_base, CPTX_VQX_MISC_INT(0, 0), 536 + vqx_misc_int.u); 537 + } 538 + 539 + static void cptvf_clear_swerr_intr(struct cpt_vf *cptvf) 540 + { 541 + union cptx_vqx_misc_int vqx_misc_int; 542 + 543 + vqx_misc_int.u = cpt_read_csr64(cptvf->reg_base, 544 + CPTX_VQX_MISC_INT(0, 0)); 545 + /* W1C for the VF */ 546 + vqx_misc_int.s.swerr = 1; 547 + cpt_write_csr64(cptvf->reg_base, CPTX_VQX_MISC_INT(0, 0), 548 + vqx_misc_int.u); 549 + } 550 + 551 + static u64 cptvf_read_vf_misc_intr_status(struct cpt_vf *cptvf) 552 + { 553 + return cpt_read_csr64(cptvf->reg_base, CPTX_VQX_MISC_INT(0, 0)); 554 + } 555 + 556 + static irqreturn_t cptvf_misc_intr_handler(int irq, void *cptvf_irq) 557 + { 558 + struct cpt_vf *cptvf = (struct cpt_vf *)cptvf_irq; 559 + struct pci_dev *pdev = cptvf->pdev; 560 + u64 intr; 561 + 562 + intr = cptvf_read_vf_misc_intr_status(cptvf); 563 + /*Check for MISC interrupt types*/ 564 + if (likely(intr & CPT_VF_INTR_MBOX_MASK)) { 565 + dev_err(&pdev->dev, "Mailbox interrupt 0x%llx on CPT VF %d\n", 566 + intr, cptvf->vfid); 567 + cptvf_handle_mbox_intr(cptvf); 568 + cptvf_clear_mbox_intr(cptvf); 569 + } else if (unlikely(intr & CPT_VF_INTR_DOVF_MASK)) { 570 + cptvf_clear_dovf_intr(cptvf); 571 + /*Clear doorbell count*/ 572 + cptvf_write_vq_doorbell(cptvf, 0); 573 + dev_err(&pdev->dev, "Doorbell overflow error interrupt 0x%llx on CPT VF %d\n", 574 + intr, cptvf->vfid); 575 + } else if (unlikely(intr & CPT_VF_INTR_IRDE_MASK)) { 576 + cptvf_clear_irde_intr(cptvf); 577 + dev_err(&pdev->dev, "Instruction NCB read error interrupt 0x%llx on CPT VF %d\n", 578 + intr, cptvf->vfid); 579 + } else if (unlikely(intr & CPT_VF_INTR_NWRP_MASK)) { 580 + cptvf_clear_nwrp_intr(cptvf); 581 + dev_err(&pdev->dev, "NCB response write error interrupt 0x%llx on CPT VF %d\n", 582 + intr, cptvf->vfid); 583 + } else if (unlikely(intr & CPT_VF_INTR_SERR_MASK)) { 584 + cptvf_clear_swerr_intr(cptvf); 585 + dev_err(&pdev->dev, "Software error interrupt 0x%llx on CPT VF %d\n", 586 + intr, cptvf->vfid); 587 + } else { 588 + dev_err(&pdev->dev, "Unhandled interrupt in CPT VF %d\n", 589 + cptvf->vfid); 590 + } 591 + 592 + return IRQ_HANDLED; 593 + } 594 + 595 + static inline struct cptvf_wqe *get_cptvf_vq_wqe(struct cpt_vf *cptvf, 596 + int qno) 597 + { 598 + struct cptvf_wqe_info *nwqe_info; 599 + 600 + if (unlikely(qno >= cptvf->nr_queues)) 601 + return NULL; 602 + nwqe_info = (struct cptvf_wqe_info *)cptvf->wqe_info; 603 + 604 + return &nwqe_info->vq_wqe[qno]; 605 + } 606 + 607 + static inline u32 cptvf_read_vq_done_count(struct cpt_vf *cptvf) 608 + { 609 + union cptx_vqx_done vqx_done; 610 + 611 + vqx_done.u = cpt_read_csr64(cptvf->reg_base, CPTX_VQX_DONE(0, 0)); 612 + return vqx_done.s.done; 613 + } 614 + 615 + static inline void cptvf_write_vq_done_ack(struct cpt_vf *cptvf, 616 + u32 ackcnt) 617 + { 618 + union cptx_vqx_done_ack vqx_dack_cnt; 619 + 620 + vqx_dack_cnt.u = cpt_read_csr64(cptvf->reg_base, 621 + CPTX_VQX_DONE_ACK(0, 0)); 622 + vqx_dack_cnt.s.done_ack = ackcnt; 623 + cpt_write_csr64(cptvf->reg_base, CPTX_VQX_DONE_ACK(0, 0), 624 + vqx_dack_cnt.u); 625 + } 626 + 627 + static irqreturn_t cptvf_done_intr_handler(int irq, void *cptvf_irq) 628 + { 629 + struct cpt_vf *cptvf = (struct cpt_vf *)cptvf_irq; 630 + struct pci_dev *pdev = cptvf->pdev; 631 + /* Read the number of completions */ 632 + u32 intr = cptvf_read_vq_done_count(cptvf); 633 + 634 + if (intr) { 635 + struct cptvf_wqe *wqe; 636 + 637 + /* Acknowledge the number of 638 + * scheduled completions for processing 639 + */ 640 + cptvf_write_vq_done_ack(cptvf, intr); 641 + wqe = get_cptvf_vq_wqe(cptvf, 0); 642 + if (unlikely(!wqe)) { 643 + dev_err(&pdev->dev, "No work to schedule for VF (%d)", 644 + cptvf->vfid); 645 + return IRQ_NONE; 646 + } 647 + tasklet_hi_schedule(&wqe->twork); 648 + } 649 + 650 + return IRQ_HANDLED; 651 + } 652 + 653 + static int cptvf_register_misc_intr(struct cpt_vf *cptvf) 654 + { 655 + struct pci_dev *pdev = cptvf->pdev; 656 + int ret; 657 + 658 + /* Register misc interrupt handlers */ 659 + ret = request_irq(cptvf->msix_entries[CPT_VF_INT_VEC_E_MISC].vector, 660 + cptvf_misc_intr_handler, 0, "CPT VF misc intr", 661 + cptvf); 662 + if (ret) 663 + goto fail; 664 + 665 + cptvf->irq_allocated[CPT_VF_INT_VEC_E_MISC] = true; 666 + 667 + /* Enable mailbox interrupt */ 668 + cptvf_enable_mbox_interrupts(cptvf); 669 + cptvf_enable_swerr_interrupts(cptvf); 670 + 671 + return 0; 672 + 673 + fail: 674 + dev_err(&pdev->dev, "Request misc irq failed"); 675 + cptvf_free_all_interrupts(cptvf); 676 + return ret; 677 + } 678 + 679 + static int cptvf_register_done_intr(struct cpt_vf *cptvf) 680 + { 681 + struct pci_dev *pdev = cptvf->pdev; 682 + int ret; 683 + 684 + /* Register DONE interrupt handlers */ 685 + ret = request_irq(cptvf->msix_entries[CPT_VF_INT_VEC_E_DONE].vector, 686 + cptvf_done_intr_handler, 0, "CPT VF done intr", 687 + cptvf); 688 + if (ret) 689 + goto fail; 690 + 691 + cptvf->irq_allocated[CPT_VF_INT_VEC_E_DONE] = true; 692 + 693 + /* Enable mailbox interrupt */ 694 + cptvf_enable_done_interrupts(cptvf); 695 + return 0; 696 + 697 + fail: 698 + dev_err(&pdev->dev, "Request done irq failed\n"); 699 + cptvf_free_all_interrupts(cptvf); 700 + return ret; 701 + } 702 + 703 + static void cptvf_unregister_interrupts(struct cpt_vf *cptvf) 704 + { 705 + cptvf_free_all_interrupts(cptvf); 706 + cptvf_disable_msix(cptvf); 707 + } 708 + 709 + static void cptvf_set_irq_affinity(struct cpt_vf *cptvf) 710 + { 711 + struct pci_dev *pdev = cptvf->pdev; 712 + int vec, cpu; 713 + int irqnum; 714 + 715 + for (vec = 0; vec < CPT_VF_MSIX_VECTORS; vec++) { 716 + if (!cptvf->irq_allocated[vec]) 717 + continue; 718 + 719 + if (!zalloc_cpumask_var(&cptvf->affinity_mask[vec], 720 + GFP_KERNEL)) { 721 + dev_err(&pdev->dev, "Allocation failed for affinity_mask for VF %d", 722 + cptvf->vfid); 723 + return; 724 + } 725 + 726 + cpu = cptvf->vfid % num_online_cpus(); 727 + cpumask_set_cpu(cpumask_local_spread(cpu, cptvf->node), 728 + cptvf->affinity_mask[vec]); 729 + irqnum = cptvf->msix_entries[vec].vector; 730 + irq_set_affinity_hint(irqnum, cptvf->affinity_mask[vec]); 731 + } 732 + } 733 + 734 + static void cptvf_write_vq_saddr(struct cpt_vf *cptvf, u64 val) 735 + { 736 + union cptx_vqx_saddr vqx_saddr; 737 + 738 + vqx_saddr.u = val; 739 + cpt_write_csr64(cptvf->reg_base, CPTX_VQX_SADDR(0, 0), vqx_saddr.u); 740 + } 741 + 742 + void cptvf_device_init(struct cpt_vf *cptvf) 743 + { 744 + u64 base_addr = 0; 745 + 746 + /* Disable the VQ */ 747 + cptvf_write_vq_ctl(cptvf, 0); 748 + /* Reset the doorbell */ 749 + cptvf_write_vq_doorbell(cptvf, 0); 750 + /* Clear inflight */ 751 + cptvf_write_vq_inprog(cptvf, 0); 752 + /* Write VQ SADDR */ 753 + /* TODO: for now only one queue, so hard coded */ 754 + base_addr = (u64)(cptvf->cqinfo.queue[0].qhead->dma_addr); 755 + cptvf_write_vq_saddr(cptvf, base_addr); 756 + /* Configure timerhold / coalescence */ 757 + cptvf_write_vq_done_timewait(cptvf, CPT_TIMER_THOLD); 758 + cptvf_write_vq_done_numwait(cptvf, 1); 759 + /* Enable the VQ */ 760 + cptvf_write_vq_ctl(cptvf, 1); 761 + /* Flag the VF ready */ 762 + cptvf->flags |= CPT_FLAG_DEVICE_READY; 763 + } 764 + 765 + static int cptvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 766 + { 767 + struct device *dev = &pdev->dev; 768 + struct cpt_vf *cptvf; 769 + int err; 770 + 771 + cptvf = devm_kzalloc(dev, sizeof(*cptvf), GFP_KERNEL); 772 + if (!cptvf) 773 + return -ENOMEM; 774 + 775 + pci_set_drvdata(pdev, cptvf); 776 + cptvf->pdev = pdev; 777 + err = pci_enable_device(pdev); 778 + if (err) { 779 + dev_err(dev, "Failed to enable PCI device\n"); 780 + pci_set_drvdata(pdev, NULL); 781 + return err; 782 + } 783 + 784 + err = pci_request_regions(pdev, DRV_NAME); 785 + if (err) { 786 + dev_err(dev, "PCI request regions failed 0x%x\n", err); 787 + goto cptvf_err_disable_device; 788 + } 789 + /* Mark as VF driver */ 790 + cptvf->flags |= CPT_FLAG_VF_DRIVER; 791 + err = pci_set_dma_mask(pdev, DMA_BIT_MASK(48)); 792 + if (err) { 793 + dev_err(dev, "Unable to get usable DMA configuration\n"); 794 + goto cptvf_err_release_regions; 795 + } 796 + 797 + err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(48)); 798 + if (err) { 799 + dev_err(dev, "Unable to get 48-bit DMA for consistent allocations\n"); 800 + goto cptvf_err_release_regions; 801 + } 802 + 803 + /* MAP PF's configuration registers */ 804 + cptvf->reg_base = pcim_iomap(pdev, 0, 0); 805 + if (!cptvf->reg_base) { 806 + dev_err(dev, "Cannot map config register space, aborting\n"); 807 + err = -ENOMEM; 808 + goto cptvf_err_release_regions; 809 + } 810 + 811 + cptvf->node = dev_to_node(&pdev->dev); 812 + /* Enable MSI-X */ 813 + err = cptvf_enable_msix(cptvf); 814 + if (err) { 815 + dev_err(dev, "cptvf_enable_msix() failed"); 816 + goto cptvf_err_release_regions; 817 + } 818 + 819 + /* Register mailbox interrupts */ 820 + cptvf_register_misc_intr(cptvf); 821 + 822 + /* Check ready with PF */ 823 + /* Gets chip ID / device Id from PF if ready */ 824 + err = cptvf_check_pf_ready(cptvf); 825 + if (err) { 826 + dev_err(dev, "PF not responding to READY msg"); 827 + goto cptvf_err_release_regions; 828 + } 829 + 830 + /* CPT VF software resources initialization */ 831 + cptvf->cqinfo.qchunksize = CPT_CMD_QCHUNK_SIZE; 832 + err = cptvf_sw_init(cptvf, CPT_CMD_QLEN, CPT_NUM_QS_PER_VF); 833 + if (err) { 834 + dev_err(dev, "cptvf_sw_init() failed"); 835 + goto cptvf_err_release_regions; 836 + } 837 + /* Convey VQ LEN to PF */ 838 + err = cptvf_send_vq_size_msg(cptvf); 839 + if (err) { 840 + dev_err(dev, "PF not responding to QLEN msg"); 841 + goto cptvf_err_release_regions; 842 + } 843 + 844 + /* CPT VF device initialization */ 845 + cptvf_device_init(cptvf); 846 + /* Send msg to PF to assign currnet Q to required group */ 847 + cptvf->vfgrp = 1; 848 + err = cptvf_send_vf_to_grp_msg(cptvf); 849 + if (err) { 850 + dev_err(dev, "PF not responding to VF_GRP msg"); 851 + goto cptvf_err_release_regions; 852 + } 853 + 854 + cptvf->priority = 1; 855 + err = cptvf_send_vf_priority_msg(cptvf); 856 + if (err) { 857 + dev_err(dev, "PF not responding to VF_PRIO msg"); 858 + goto cptvf_err_release_regions; 859 + } 860 + /* Register DONE interrupts */ 861 + err = cptvf_register_done_intr(cptvf); 862 + if (err) 863 + goto cptvf_err_release_regions; 864 + 865 + /* Set irq affinity masks */ 866 + cptvf_set_irq_affinity(cptvf); 867 + /* Convey UP to PF */ 868 + err = cptvf_send_vf_up(cptvf); 869 + if (err) { 870 + dev_err(dev, "PF not responding to UP msg"); 871 + goto cptvf_up_fail; 872 + } 873 + err = cvm_crypto_init(cptvf); 874 + if (err) { 875 + dev_err(dev, "Algorithm register failed\n"); 876 + goto cptvf_up_fail; 877 + } 878 + return 0; 879 + 880 + cptvf_up_fail: 881 + cptvf_unregister_interrupts(cptvf); 882 + cptvf_err_release_regions: 883 + pci_release_regions(pdev); 884 + cptvf_err_disable_device: 885 + pci_disable_device(pdev); 886 + pci_set_drvdata(pdev, NULL); 887 + 888 + return err; 889 + } 890 + 891 + static void cptvf_remove(struct pci_dev *pdev) 892 + { 893 + struct cpt_vf *cptvf = pci_get_drvdata(pdev); 894 + 895 + if (!cptvf) 896 + dev_err(&pdev->dev, "Invalid CPT-VF device\n"); 897 + 898 + /* Convey DOWN to PF */ 899 + if (cptvf_send_vf_down(cptvf)) { 900 + dev_err(&pdev->dev, "PF not responding to DOWN msg"); 901 + } else { 902 + cptvf_unregister_interrupts(cptvf); 903 + cptvf_sw_cleanup(cptvf); 904 + pci_set_drvdata(pdev, NULL); 905 + pci_release_regions(pdev); 906 + pci_disable_device(pdev); 907 + cvm_crypto_exit(); 908 + } 909 + } 910 + 911 + static void cptvf_shutdown(struct pci_dev *pdev) 912 + { 913 + cptvf_remove(pdev); 914 + } 915 + 916 + /* Supported devices */ 917 + static const struct pci_device_id cptvf_id_table[] = { 918 + {PCI_VDEVICE(CAVIUM, CPT_81XX_PCI_VF_DEVICE_ID), 0}, 919 + { 0, } /* end of table */ 920 + }; 921 + 922 + static struct pci_driver cptvf_pci_driver = { 923 + .name = DRV_NAME, 924 + .id_table = cptvf_id_table, 925 + .probe = cptvf_probe, 926 + .remove = cptvf_remove, 927 + .shutdown = cptvf_shutdown, 928 + }; 929 + 930 + module_pci_driver(cptvf_pci_driver); 931 + 932 + MODULE_AUTHOR("George Cherian <george.cherian@cavium.com>"); 933 + MODULE_DESCRIPTION("Cavium Thunder CPT Virtual Function Driver"); 934 + MODULE_LICENSE("GPL v2"); 935 + MODULE_VERSION(DRV_VERSION); 936 + MODULE_DEVICE_TABLE(pci, cptvf_id_table);
+211
drivers/crypto/cavium/cpt/cptvf_mbox.c
··· 1 + /* 2 + * Copyright (C) 2016 Cavium, Inc. 3 + * 4 + * This program is free software; you can redistribute it and/or modify 5 + * it under the terms of version 2 of the GNU General Public License 6 + * as published by the Free Software Foundation. 7 + */ 8 + 9 + #include "cptvf.h" 10 + 11 + static void cptvf_send_msg_to_pf(struct cpt_vf *cptvf, struct cpt_mbox *mbx) 12 + { 13 + /* Writing mbox(1) causes interrupt */ 14 + cpt_write_csr64(cptvf->reg_base, CPTX_VFX_PF_MBOXX(0, 0, 0), 15 + mbx->msg); 16 + cpt_write_csr64(cptvf->reg_base, CPTX_VFX_PF_MBOXX(0, 0, 1), 17 + mbx->data); 18 + } 19 + 20 + /* ACKs PF's mailbox message 21 + */ 22 + void cptvf_mbox_send_ack(struct cpt_vf *cptvf, struct cpt_mbox *mbx) 23 + { 24 + mbx->msg = CPT_MBOX_MSG_TYPE_ACK; 25 + cptvf_send_msg_to_pf(cptvf, mbx); 26 + } 27 + 28 + /* NACKs PF's mailbox message that VF is not able to 29 + * complete the action 30 + */ 31 + void cptvf_mbox_send_nack(struct cpt_vf *cptvf, struct cpt_mbox *mbx) 32 + { 33 + mbx->msg = CPT_MBOX_MSG_TYPE_NACK; 34 + cptvf_send_msg_to_pf(cptvf, mbx); 35 + } 36 + 37 + /* Interrupt handler to handle mailbox messages from VFs */ 38 + void cptvf_handle_mbox_intr(struct cpt_vf *cptvf) 39 + { 40 + struct cpt_mbox mbx = {}; 41 + 42 + /* 43 + * MBOX[0] contains msg 44 + * MBOX[1] contains data 45 + */ 46 + mbx.msg = cpt_read_csr64(cptvf->reg_base, CPTX_VFX_PF_MBOXX(0, 0, 0)); 47 + mbx.data = cpt_read_csr64(cptvf->reg_base, CPTX_VFX_PF_MBOXX(0, 0, 1)); 48 + dev_dbg(&cptvf->pdev->dev, "%s: Mailbox msg 0x%llx from PF\n", 49 + __func__, mbx.msg); 50 + switch (mbx.msg) { 51 + case CPT_MSG_READY: 52 + { 53 + cptvf->pf_acked = true; 54 + cptvf->vfid = mbx.data; 55 + dev_dbg(&cptvf->pdev->dev, "Received VFID %d\n", cptvf->vfid); 56 + break; 57 + } 58 + case CPT_MSG_QBIND_GRP: 59 + cptvf->pf_acked = true; 60 + cptvf->vftype = mbx.data; 61 + dev_dbg(&cptvf->pdev->dev, "VF %d type %s group %d\n", 62 + cptvf->vfid, ((mbx.data == SE_TYPES) ? "SE" : "AE"), 63 + cptvf->vfgrp); 64 + break; 65 + case CPT_MBOX_MSG_TYPE_ACK: 66 + cptvf->pf_acked = true; 67 + break; 68 + case CPT_MBOX_MSG_TYPE_NACK: 69 + cptvf->pf_nacked = true; 70 + break; 71 + default: 72 + dev_err(&cptvf->pdev->dev, "Invalid msg from PF, msg 0x%llx\n", 73 + mbx.msg); 74 + break; 75 + } 76 + } 77 + 78 + static int cptvf_send_msg_to_pf_timeout(struct cpt_vf *cptvf, 79 + struct cpt_mbox *mbx) 80 + { 81 + int timeout = CPT_MBOX_MSG_TIMEOUT; 82 + int sleep = 10; 83 + 84 + cptvf->pf_acked = false; 85 + cptvf->pf_nacked = false; 86 + cptvf_send_msg_to_pf(cptvf, mbx); 87 + /* Wait for previous message to be acked, timeout 2sec */ 88 + while (!cptvf->pf_acked) { 89 + if (cptvf->pf_nacked) 90 + return -EINVAL; 91 + msleep(sleep); 92 + if (cptvf->pf_acked) 93 + break; 94 + timeout -= sleep; 95 + if (!timeout) { 96 + dev_err(&cptvf->pdev->dev, "PF didn't ack to mbox msg %llx from VF%u\n", 97 + (mbx->msg & 0xFF), cptvf->vfid); 98 + return -EBUSY; 99 + } 100 + } 101 + 102 + return 0; 103 + } 104 + 105 + /* 106 + * Checks if VF is able to comminicate with PF 107 + * and also gets the CPT number this VF is associated to. 108 + */ 109 + int cptvf_check_pf_ready(struct cpt_vf *cptvf) 110 + { 111 + struct pci_dev *pdev = cptvf->pdev; 112 + struct cpt_mbox mbx = {}; 113 + 114 + mbx.msg = CPT_MSG_READY; 115 + if (cptvf_send_msg_to_pf_timeout(cptvf, &mbx)) { 116 + dev_err(&pdev->dev, "PF didn't respond to READY msg\n"); 117 + return -EBUSY; 118 + } 119 + 120 + return 0; 121 + } 122 + 123 + /* 124 + * Communicate VQs size to PF to program CPT(0)_PF_Q(0-15)_CTL of the VF. 125 + * Must be ACKed. 126 + */ 127 + int cptvf_send_vq_size_msg(struct cpt_vf *cptvf) 128 + { 129 + struct pci_dev *pdev = cptvf->pdev; 130 + struct cpt_mbox mbx = {}; 131 + 132 + mbx.msg = CPT_MSG_QLEN; 133 + mbx.data = cptvf->qsize; 134 + if (cptvf_send_msg_to_pf_timeout(cptvf, &mbx)) { 135 + dev_err(&pdev->dev, "PF didn't respond to vq_size msg\n"); 136 + return -EBUSY; 137 + } 138 + 139 + return 0; 140 + } 141 + 142 + /* 143 + * Communicate VF group required to PF and get the VQ binded to that group 144 + */ 145 + int cptvf_send_vf_to_grp_msg(struct cpt_vf *cptvf) 146 + { 147 + struct pci_dev *pdev = cptvf->pdev; 148 + struct cpt_mbox mbx = {}; 149 + 150 + mbx.msg = CPT_MSG_QBIND_GRP; 151 + /* Convey group of the VF */ 152 + mbx.data = cptvf->vfgrp; 153 + if (cptvf_send_msg_to_pf_timeout(cptvf, &mbx)) { 154 + dev_err(&pdev->dev, "PF didn't respond to vf_type msg\n"); 155 + return -EBUSY; 156 + } 157 + 158 + return 0; 159 + } 160 + 161 + /* 162 + * Communicate VF group required to PF and get the VQ binded to that group 163 + */ 164 + int cptvf_send_vf_priority_msg(struct cpt_vf *cptvf) 165 + { 166 + struct pci_dev *pdev = cptvf->pdev; 167 + struct cpt_mbox mbx = {}; 168 + 169 + mbx.msg = CPT_MSG_VQ_PRIORITY; 170 + /* Convey group of the VF */ 171 + mbx.data = cptvf->priority; 172 + if (cptvf_send_msg_to_pf_timeout(cptvf, &mbx)) { 173 + dev_err(&pdev->dev, "PF didn't respond to vf_type msg\n"); 174 + return -EBUSY; 175 + } 176 + return 0; 177 + } 178 + 179 + /* 180 + * Communicate to PF that VF is UP and running 181 + */ 182 + int cptvf_send_vf_up(struct cpt_vf *cptvf) 183 + { 184 + struct pci_dev *pdev = cptvf->pdev; 185 + struct cpt_mbox mbx = {}; 186 + 187 + mbx.msg = CPT_MSG_VF_UP; 188 + if (cptvf_send_msg_to_pf_timeout(cptvf, &mbx)) { 189 + dev_err(&pdev->dev, "PF didn't respond to UP msg\n"); 190 + return -EBUSY; 191 + } 192 + 193 + return 0; 194 + } 195 + 196 + /* 197 + * Communicate to PF that VF is DOWN and running 198 + */ 199 + int cptvf_send_vf_down(struct cpt_vf *cptvf) 200 + { 201 + struct pci_dev *pdev = cptvf->pdev; 202 + struct cpt_mbox mbx = {}; 203 + 204 + mbx.msg = CPT_MSG_VF_DOWN; 205 + if (cptvf_send_msg_to_pf_timeout(cptvf, &mbx)) { 206 + dev_err(&pdev->dev, "PF didn't respond to DOWN msg\n"); 207 + return -EBUSY; 208 + } 209 + 210 + return 0; 211 + }
+593
drivers/crypto/cavium/cpt/cptvf_reqmanager.c
··· 1 + /* 2 + * Copyright (C) 2016 Cavium, Inc. 3 + * 4 + * This program is free software; you can redistribute it and/or modify 5 + * it under the terms of version 2 of the GNU General Public License 6 + * as published by the Free Software Foundation. 7 + */ 8 + 9 + #include "cptvf.h" 10 + #include "request_manager.h" 11 + 12 + /** 13 + * get_free_pending_entry - get free entry from pending queue 14 + * @param pqinfo: pending_qinfo structure 15 + * @param qno: queue number 16 + */ 17 + static struct pending_entry *get_free_pending_entry(struct pending_queue *q, 18 + int qlen) 19 + { 20 + struct pending_entry *ent = NULL; 21 + 22 + ent = &q->head[q->rear]; 23 + if (unlikely(ent->busy)) { 24 + ent = NULL; 25 + goto no_free_entry; 26 + } 27 + 28 + q->rear++; 29 + if (unlikely(q->rear == qlen)) 30 + q->rear = 0; 31 + 32 + no_free_entry: 33 + return ent; 34 + } 35 + 36 + static inline void pending_queue_inc_front(struct pending_qinfo *pqinfo, 37 + int qno) 38 + { 39 + struct pending_queue *queue = &pqinfo->queue[qno]; 40 + 41 + queue->front++; 42 + if (unlikely(queue->front == pqinfo->qlen)) 43 + queue->front = 0; 44 + } 45 + 46 + static int setup_sgio_components(struct cpt_vf *cptvf, struct buf_ptr *list, 47 + int buf_count, u8 *buffer) 48 + { 49 + int ret = 0, i, j; 50 + int components; 51 + struct sglist_component *sg_ptr = NULL; 52 + struct pci_dev *pdev = cptvf->pdev; 53 + 54 + if (unlikely(!list)) { 55 + dev_err(&pdev->dev, "Input List pointer is NULL\n"); 56 + return -EFAULT; 57 + } 58 + 59 + for (i = 0; i < buf_count; i++) { 60 + if (likely(list[i].vptr)) { 61 + list[i].dma_addr = dma_map_single(&pdev->dev, 62 + list[i].vptr, 63 + list[i].size, 64 + DMA_BIDIRECTIONAL); 65 + if (unlikely(dma_mapping_error(&pdev->dev, 66 + list[i].dma_addr))) { 67 + dev_err(&pdev->dev, "DMA map kernel buffer failed for component: %d\n", 68 + i); 69 + ret = -EIO; 70 + goto sg_cleanup; 71 + } 72 + } 73 + } 74 + 75 + components = buf_count / 4; 76 + sg_ptr = (struct sglist_component *)buffer; 77 + for (i = 0; i < components; i++) { 78 + sg_ptr->u.s.len0 = cpu_to_be16(list[i * 4 + 0].size); 79 + sg_ptr->u.s.len1 = cpu_to_be16(list[i * 4 + 1].size); 80 + sg_ptr->u.s.len2 = cpu_to_be16(list[i * 4 + 2].size); 81 + sg_ptr->u.s.len3 = cpu_to_be16(list[i * 4 + 3].size); 82 + sg_ptr->ptr0 = cpu_to_be64(list[i * 4 + 0].dma_addr); 83 + sg_ptr->ptr1 = cpu_to_be64(list[i * 4 + 1].dma_addr); 84 + sg_ptr->ptr2 = cpu_to_be64(list[i * 4 + 2].dma_addr); 85 + sg_ptr->ptr3 = cpu_to_be64(list[i * 4 + 3].dma_addr); 86 + sg_ptr++; 87 + } 88 + 89 + components = buf_count % 4; 90 + 91 + switch (components) { 92 + case 3: 93 + sg_ptr->u.s.len2 = cpu_to_be16(list[i * 4 + 2].size); 94 + sg_ptr->ptr2 = cpu_to_be64(list[i * 4 + 2].dma_addr); 95 + /* Fall through */ 96 + case 2: 97 + sg_ptr->u.s.len1 = cpu_to_be16(list[i * 4 + 1].size); 98 + sg_ptr->ptr1 = cpu_to_be64(list[i * 4 + 1].dma_addr); 99 + /* Fall through */ 100 + case 1: 101 + sg_ptr->u.s.len0 = cpu_to_be16(list[i * 4 + 0].size); 102 + sg_ptr->ptr0 = cpu_to_be64(list[i * 4 + 0].dma_addr); 103 + break; 104 + default: 105 + break; 106 + } 107 + 108 + return ret; 109 + 110 + sg_cleanup: 111 + for (j = 0; j < i; j++) { 112 + if (list[j].dma_addr) { 113 + dma_unmap_single(&pdev->dev, list[i].dma_addr, 114 + list[i].size, DMA_BIDIRECTIONAL); 115 + } 116 + 117 + list[j].dma_addr = 0; 118 + } 119 + 120 + return ret; 121 + } 122 + 123 + static inline int setup_sgio_list(struct cpt_vf *cptvf, 124 + struct cpt_info_buffer *info, 125 + struct cpt_request_info *req) 126 + { 127 + u16 g_sz_bytes = 0, s_sz_bytes = 0; 128 + int ret = 0; 129 + struct pci_dev *pdev = cptvf->pdev; 130 + 131 + if (req->incnt > MAX_SG_IN_CNT || req->outcnt > MAX_SG_OUT_CNT) { 132 + dev_err(&pdev->dev, "Request SG components are higher than supported\n"); 133 + ret = -EINVAL; 134 + goto scatter_gather_clean; 135 + } 136 + 137 + /* Setup gather (input) components */ 138 + g_sz_bytes = ((req->incnt + 3) / 4) * sizeof(struct sglist_component); 139 + info->gather_components = kzalloc(g_sz_bytes, GFP_KERNEL); 140 + if (!info->gather_components) { 141 + ret = -ENOMEM; 142 + goto scatter_gather_clean; 143 + } 144 + 145 + ret = setup_sgio_components(cptvf, req->in, 146 + req->incnt, 147 + info->gather_components); 148 + if (ret) { 149 + dev_err(&pdev->dev, "Failed to setup gather list\n"); 150 + ret = -EFAULT; 151 + goto scatter_gather_clean; 152 + } 153 + 154 + /* Setup scatter (output) components */ 155 + s_sz_bytes = ((req->outcnt + 3) / 4) * sizeof(struct sglist_component); 156 + info->scatter_components = kzalloc(s_sz_bytes, GFP_KERNEL); 157 + if (!info->scatter_components) { 158 + ret = -ENOMEM; 159 + goto scatter_gather_clean; 160 + } 161 + 162 + ret = setup_sgio_components(cptvf, req->out, 163 + req->outcnt, 164 + info->scatter_components); 165 + if (ret) { 166 + dev_err(&pdev->dev, "Failed to setup gather list\n"); 167 + ret = -EFAULT; 168 + goto scatter_gather_clean; 169 + } 170 + 171 + /* Create and initialize DPTR */ 172 + info->dlen = g_sz_bytes + s_sz_bytes + SG_LIST_HDR_SIZE; 173 + info->in_buffer = kzalloc(info->dlen, GFP_KERNEL); 174 + if (!info->in_buffer) { 175 + ret = -ENOMEM; 176 + goto scatter_gather_clean; 177 + } 178 + 179 + ((u16 *)info->in_buffer)[0] = req->outcnt; 180 + ((u16 *)info->in_buffer)[1] = req->incnt; 181 + ((u16 *)info->in_buffer)[2] = 0; 182 + ((u16 *)info->in_buffer)[3] = 0; 183 + *(u64 *)info->in_buffer = cpu_to_be64p((u64 *)info->in_buffer); 184 + 185 + memcpy(&info->in_buffer[8], info->gather_components, 186 + g_sz_bytes); 187 + memcpy(&info->in_buffer[8 + g_sz_bytes], 188 + info->scatter_components, s_sz_bytes); 189 + 190 + info->dptr_baddr = dma_map_single(&pdev->dev, 191 + (void *)info->in_buffer, 192 + info->dlen, 193 + DMA_BIDIRECTIONAL); 194 + if (dma_mapping_error(&pdev->dev, info->dptr_baddr)) { 195 + dev_err(&pdev->dev, "Mapping DPTR Failed %d\n", info->dlen); 196 + ret = -EIO; 197 + goto scatter_gather_clean; 198 + } 199 + 200 + /* Create and initialize RPTR */ 201 + info->out_buffer = kzalloc(COMPLETION_CODE_SIZE, GFP_KERNEL); 202 + if (!info->out_buffer) { 203 + ret = -ENOMEM; 204 + goto scatter_gather_clean; 205 + } 206 + 207 + *((u64 *)info->out_buffer) = ~((u64)COMPLETION_CODE_INIT); 208 + info->alternate_caddr = (u64 *)info->out_buffer; 209 + info->rptr_baddr = dma_map_single(&pdev->dev, 210 + (void *)info->out_buffer, 211 + COMPLETION_CODE_SIZE, 212 + DMA_BIDIRECTIONAL); 213 + if (dma_mapping_error(&pdev->dev, info->rptr_baddr)) { 214 + dev_err(&pdev->dev, "Mapping RPTR Failed %d\n", 215 + COMPLETION_CODE_SIZE); 216 + ret = -EIO; 217 + goto scatter_gather_clean; 218 + } 219 + 220 + return 0; 221 + 222 + scatter_gather_clean: 223 + return ret; 224 + } 225 + 226 + int send_cpt_command(struct cpt_vf *cptvf, union cpt_inst_s *cmd, 227 + u32 qno) 228 + { 229 + struct pci_dev *pdev = cptvf->pdev; 230 + struct command_qinfo *qinfo = NULL; 231 + struct command_queue *queue; 232 + struct command_chunk *chunk; 233 + u8 *ent; 234 + int ret = 0; 235 + 236 + if (unlikely(qno >= cptvf->nr_queues)) { 237 + dev_err(&pdev->dev, "Invalid queue (qno: %d, nr_queues: %d)\n", 238 + qno, cptvf->nr_queues); 239 + return -EINVAL; 240 + } 241 + 242 + qinfo = &cptvf->cqinfo; 243 + queue = &qinfo->queue[qno]; 244 + /* lock commad queue */ 245 + spin_lock(&queue->lock); 246 + ent = &queue->qhead->head[queue->idx * qinfo->cmd_size]; 247 + memcpy(ent, (void *)cmd, qinfo->cmd_size); 248 + 249 + if (++queue->idx >= queue->qhead->size / 64) { 250 + struct hlist_node *node; 251 + 252 + hlist_for_each(node, &queue->chead) { 253 + chunk = hlist_entry(node, struct command_chunk, 254 + nextchunk); 255 + if (chunk == queue->qhead) { 256 + continue; 257 + } else { 258 + queue->qhead = chunk; 259 + break; 260 + } 261 + } 262 + queue->idx = 0; 263 + } 264 + /* make sure all memory stores are done before ringing doorbell */ 265 + smp_wmb(); 266 + cptvf_write_vq_doorbell(cptvf, 1); 267 + /* unlock command queue */ 268 + spin_unlock(&queue->lock); 269 + 270 + return ret; 271 + } 272 + 273 + void do_request_cleanup(struct cpt_vf *cptvf, 274 + struct cpt_info_buffer *info) 275 + { 276 + int i; 277 + struct pci_dev *pdev = cptvf->pdev; 278 + struct cpt_request_info *req; 279 + 280 + if (info->dptr_baddr) 281 + dma_unmap_single(&pdev->dev, info->dptr_baddr, 282 + info->dlen, DMA_BIDIRECTIONAL); 283 + 284 + if (info->rptr_baddr) 285 + dma_unmap_single(&pdev->dev, info->rptr_baddr, 286 + COMPLETION_CODE_SIZE, DMA_BIDIRECTIONAL); 287 + 288 + if (info->comp_baddr) 289 + dma_unmap_single(&pdev->dev, info->comp_baddr, 290 + sizeof(union cpt_res_s), DMA_BIDIRECTIONAL); 291 + 292 + if (info->req) { 293 + req = info->req; 294 + for (i = 0; i < req->outcnt; i++) { 295 + if (req->out[i].dma_addr) 296 + dma_unmap_single(&pdev->dev, 297 + req->out[i].dma_addr, 298 + req->out[i].size, 299 + DMA_BIDIRECTIONAL); 300 + } 301 + 302 + for (i = 0; i < req->incnt; i++) { 303 + if (req->in[i].dma_addr) 304 + dma_unmap_single(&pdev->dev, 305 + req->in[i].dma_addr, 306 + req->in[i].size, 307 + DMA_BIDIRECTIONAL); 308 + } 309 + } 310 + 311 + if (info->scatter_components) 312 + kzfree(info->scatter_components); 313 + 314 + if (info->gather_components) 315 + kzfree(info->gather_components); 316 + 317 + if (info->out_buffer) 318 + kzfree(info->out_buffer); 319 + 320 + if (info->in_buffer) 321 + kzfree(info->in_buffer); 322 + 323 + if (info->completion_addr) 324 + kzfree((void *)info->completion_addr); 325 + 326 + kzfree(info); 327 + } 328 + 329 + void do_post_process(struct cpt_vf *cptvf, struct cpt_info_buffer *info) 330 + { 331 + struct pci_dev *pdev = cptvf->pdev; 332 + 333 + if (!info || !cptvf) { 334 + dev_err(&pdev->dev, "Input params are incorrect for post processing\n"); 335 + return; 336 + } 337 + 338 + do_request_cleanup(cptvf, info); 339 + } 340 + 341 + static inline void process_pending_queue(struct cpt_vf *cptvf, 342 + struct pending_qinfo *pqinfo, 343 + int qno) 344 + { 345 + struct pci_dev *pdev = cptvf->pdev; 346 + struct pending_queue *pqueue = &pqinfo->queue[qno]; 347 + struct pending_entry *pentry = NULL; 348 + struct cpt_info_buffer *info = NULL; 349 + union cpt_res_s *status = NULL; 350 + unsigned char ccode; 351 + 352 + while (1) { 353 + spin_lock_bh(&pqueue->lock); 354 + pentry = &pqueue->head[pqueue->front]; 355 + if (unlikely(!pentry->busy)) { 356 + spin_unlock_bh(&pqueue->lock); 357 + break; 358 + } 359 + 360 + info = (struct cpt_info_buffer *)pentry->post_arg; 361 + if (unlikely(!info)) { 362 + dev_err(&pdev->dev, "Pending Entry post arg NULL\n"); 363 + pending_queue_inc_front(pqinfo, qno); 364 + spin_unlock_bh(&pqueue->lock); 365 + continue; 366 + } 367 + 368 + status = (union cpt_res_s *)pentry->completion_addr; 369 + ccode = status->s.compcode; 370 + if ((status->s.compcode == CPT_COMP_E_FAULT) || 371 + (status->s.compcode == CPT_COMP_E_SWERR)) { 372 + dev_err(&pdev->dev, "Request failed with %s\n", 373 + (status->s.compcode == CPT_COMP_E_FAULT) ? 374 + "DMA Fault" : "Software error"); 375 + pentry->completion_addr = NULL; 376 + pentry->busy = false; 377 + atomic64_dec((&pqueue->pending_count)); 378 + pentry->post_arg = NULL; 379 + pending_queue_inc_front(pqinfo, qno); 380 + do_request_cleanup(cptvf, info); 381 + spin_unlock_bh(&pqueue->lock); 382 + break; 383 + } else if (status->s.compcode == COMPLETION_CODE_INIT) { 384 + /* check for timeout */ 385 + if (time_after_eq(jiffies, 386 + (info->time_in + 387 + (CPT_COMMAND_TIMEOUT * HZ)))) { 388 + dev_err(&pdev->dev, "Request timed out"); 389 + pentry->completion_addr = NULL; 390 + pentry->busy = false; 391 + atomic64_dec((&pqueue->pending_count)); 392 + pentry->post_arg = NULL; 393 + pending_queue_inc_front(pqinfo, qno); 394 + do_request_cleanup(cptvf, info); 395 + spin_unlock_bh(&pqueue->lock); 396 + break; 397 + } else if ((*info->alternate_caddr == 398 + (~COMPLETION_CODE_INIT)) && 399 + (info->extra_time < TIME_IN_RESET_COUNT)) { 400 + info->time_in = jiffies; 401 + info->extra_time++; 402 + spin_unlock_bh(&pqueue->lock); 403 + break; 404 + } 405 + } 406 + 407 + pentry->completion_addr = NULL; 408 + pentry->busy = false; 409 + pentry->post_arg = NULL; 410 + atomic64_dec((&pqueue->pending_count)); 411 + pending_queue_inc_front(pqinfo, qno); 412 + spin_unlock_bh(&pqueue->lock); 413 + 414 + do_post_process(info->cptvf, info); 415 + /* 416 + * Calling callback after we find 417 + * that the request has been serviced 418 + */ 419 + pentry->callback(ccode, pentry->callback_arg); 420 + } 421 + } 422 + 423 + int process_request(struct cpt_vf *cptvf, struct cpt_request_info *req) 424 + { 425 + int ret = 0, clear = 0, queue = 0; 426 + struct cpt_info_buffer *info = NULL; 427 + struct cptvf_request *cpt_req = NULL; 428 + union ctrl_info *ctrl = NULL; 429 + union cpt_res_s *result = NULL; 430 + struct pending_entry *pentry = NULL; 431 + struct pending_queue *pqueue = NULL; 432 + struct pci_dev *pdev = cptvf->pdev; 433 + u8 group = 0; 434 + struct cpt_vq_command vq_cmd; 435 + union cpt_inst_s cptinst; 436 + 437 + info = kzalloc(sizeof(*info), GFP_KERNEL); 438 + if (unlikely(!info)) { 439 + dev_err(&pdev->dev, "Unable to allocate memory for info_buffer\n"); 440 + return -ENOMEM; 441 + } 442 + 443 + cpt_req = (struct cptvf_request *)&req->req; 444 + ctrl = (union ctrl_info *)&req->ctrl; 445 + 446 + info->cptvf = cptvf; 447 + group = ctrl->s.grp; 448 + ret = setup_sgio_list(cptvf, info, req); 449 + if (ret) { 450 + dev_err(&pdev->dev, "Setting up SG list failed"); 451 + goto request_cleanup; 452 + } 453 + 454 + cpt_req->dlen = info->dlen; 455 + /* 456 + * Get buffer for union cpt_res_s response 457 + * structure and its physical address 458 + */ 459 + info->completion_addr = kzalloc(sizeof(union cpt_res_s), GFP_KERNEL); 460 + if (unlikely(!info->completion_addr)) { 461 + dev_err(&pdev->dev, "Unable to allocate memory for completion_addr\n"); 462 + return -ENOMEM; 463 + } 464 + 465 + result = (union cpt_res_s *)info->completion_addr; 466 + result->s.compcode = COMPLETION_CODE_INIT; 467 + info->comp_baddr = dma_map_single(&pdev->dev, 468 + (void *)info->completion_addr, 469 + sizeof(union cpt_res_s), 470 + DMA_BIDIRECTIONAL); 471 + if (dma_mapping_error(&pdev->dev, info->comp_baddr)) { 472 + dev_err(&pdev->dev, "mapping compptr Failed %lu\n", 473 + sizeof(union cpt_res_s)); 474 + ret = -EFAULT; 475 + goto request_cleanup; 476 + } 477 + 478 + /* Fill the VQ command */ 479 + vq_cmd.cmd.u64 = 0; 480 + vq_cmd.cmd.s.opcode = cpu_to_be16(cpt_req->opcode.flags); 481 + vq_cmd.cmd.s.param1 = cpu_to_be16(cpt_req->param1); 482 + vq_cmd.cmd.s.param2 = cpu_to_be16(cpt_req->param2); 483 + vq_cmd.cmd.s.dlen = cpu_to_be16(cpt_req->dlen); 484 + 485 + /* 64-bit swap for microcode data reads, not needed for addresses*/ 486 + vq_cmd.cmd.u64 = cpu_to_be64(vq_cmd.cmd.u64); 487 + vq_cmd.dptr = info->dptr_baddr; 488 + vq_cmd.rptr = info->rptr_baddr; 489 + vq_cmd.cptr.u64 = 0; 490 + vq_cmd.cptr.s.grp = group; 491 + /* Get Pending Entry to submit command */ 492 + /* Always queue 0, because 1 queue per VF */ 493 + queue = 0; 494 + pqueue = &cptvf->pqinfo.queue[queue]; 495 + 496 + if (atomic64_read(&pqueue->pending_count) > PENDING_THOLD) { 497 + dev_err(&pdev->dev, "pending threshold reached\n"); 498 + process_pending_queue(cptvf, &cptvf->pqinfo, queue); 499 + } 500 + 501 + get_pending_entry: 502 + spin_lock_bh(&pqueue->lock); 503 + pentry = get_free_pending_entry(pqueue, cptvf->pqinfo.qlen); 504 + if (unlikely(!pentry)) { 505 + spin_unlock_bh(&pqueue->lock); 506 + if (clear == 0) { 507 + process_pending_queue(cptvf, &cptvf->pqinfo, queue); 508 + clear = 1; 509 + goto get_pending_entry; 510 + } 511 + dev_err(&pdev->dev, "Get free entry failed\n"); 512 + dev_err(&pdev->dev, "queue: %d, rear: %d, front: %d\n", 513 + queue, pqueue->rear, pqueue->front); 514 + ret = -EFAULT; 515 + goto request_cleanup; 516 + } 517 + 518 + pentry->completion_addr = info->completion_addr; 519 + pentry->post_arg = (void *)info; 520 + pentry->callback = req->callback; 521 + pentry->callback_arg = req->callback_arg; 522 + info->pentry = pentry; 523 + pentry->busy = true; 524 + atomic64_inc(&pqueue->pending_count); 525 + 526 + /* Send CPT command */ 527 + info->pentry = pentry; 528 + info->time_in = jiffies; 529 + info->req = req; 530 + 531 + /* Create the CPT_INST_S type command for HW intrepretation */ 532 + cptinst.s.doneint = true; 533 + cptinst.s.res_addr = (u64)info->comp_baddr; 534 + cptinst.s.tag = 0; 535 + cptinst.s.grp = 0; 536 + cptinst.s.wq_ptr = 0; 537 + cptinst.s.ei0 = vq_cmd.cmd.u64; 538 + cptinst.s.ei1 = vq_cmd.dptr; 539 + cptinst.s.ei2 = vq_cmd.rptr; 540 + cptinst.s.ei3 = vq_cmd.cptr.u64; 541 + 542 + ret = send_cpt_command(cptvf, &cptinst, queue); 543 + spin_unlock_bh(&pqueue->lock); 544 + if (unlikely(ret)) { 545 + dev_err(&pdev->dev, "Send command failed for AE\n"); 546 + ret = -EFAULT; 547 + goto request_cleanup; 548 + } 549 + 550 + return 0; 551 + 552 + request_cleanup: 553 + dev_dbg(&pdev->dev, "Failed to submit CPT command\n"); 554 + do_request_cleanup(cptvf, info); 555 + 556 + return ret; 557 + } 558 + 559 + void vq_post_process(struct cpt_vf *cptvf, u32 qno) 560 + { 561 + struct pci_dev *pdev = cptvf->pdev; 562 + 563 + if (unlikely(qno > cptvf->nr_queues)) { 564 + dev_err(&pdev->dev, "Request for post processing on invalid pending queue: %u\n", 565 + qno); 566 + return; 567 + } 568 + 569 + process_pending_queue(cptvf, &cptvf->pqinfo, qno); 570 + } 571 + 572 + int cptvf_do_request(void *vfdev, struct cpt_request_info *req) 573 + { 574 + struct cpt_vf *cptvf = (struct cpt_vf *)vfdev; 575 + struct pci_dev *pdev = cptvf->pdev; 576 + 577 + if (!cpt_device_ready(cptvf)) { 578 + dev_err(&pdev->dev, "CPT Device is not ready"); 579 + return -ENODEV; 580 + } 581 + 582 + if ((cptvf->vftype == SE_TYPES) && (!req->ctrl.s.se_req)) { 583 + dev_err(&pdev->dev, "CPTVF-%d of SE TYPE got AE request", 584 + cptvf->vfid); 585 + return -EINVAL; 586 + } else if ((cptvf->vftype == AE_TYPES) && (req->ctrl.s.se_req)) { 587 + dev_err(&pdev->dev, "CPTVF-%d of AE TYPE got SE request", 588 + cptvf->vfid); 589 + return -EINVAL; 590 + } 591 + 592 + return process_request(cptvf, req); 593 + }
+147
drivers/crypto/cavium/cpt/request_manager.h
··· 1 + /* 2 + * Copyright (C) 2016 Cavium, Inc. 3 + * 4 + * This program is free software; you can redistribute it and/or modify it 5 + * under the terms of version 2 of the GNU General Public License 6 + * as published by the Free Software Foundation. 7 + */ 8 + 9 + #ifndef __REQUEST_MANAGER_H 10 + #define __REQUEST_MANAGER_H 11 + 12 + #include "cpt_common.h" 13 + 14 + #define TIME_IN_RESET_COUNT 5 15 + #define COMPLETION_CODE_SIZE 8 16 + #define COMPLETION_CODE_INIT 0 17 + #define PENDING_THOLD 100 18 + #define MAX_SG_IN_CNT 12 19 + #define MAX_SG_OUT_CNT 13 20 + #define SG_LIST_HDR_SIZE 8 21 + #define MAX_BUF_CNT 16 22 + 23 + union ctrl_info { 24 + u32 flags; 25 + struct { 26 + #if defined(__BIG_ENDIAN_BITFIELD) 27 + u32 reserved0:26; 28 + u32 grp:3; /* Group bits */ 29 + u32 dma_mode:2; /* DMA mode */ 30 + u32 se_req:1;/* To SE core */ 31 + #else 32 + u32 se_req:1; /* To SE core */ 33 + u32 dma_mode:2; /* DMA mode */ 34 + u32 grp:3; /* Group bits */ 35 + u32 reserved0:26; 36 + #endif 37 + } s; 38 + }; 39 + 40 + union opcode_info { 41 + u16 flags; 42 + struct { 43 + u8 major; 44 + u8 minor; 45 + } s; 46 + }; 47 + 48 + struct cptvf_request { 49 + union opcode_info opcode; 50 + u16 param1; 51 + u16 param2; 52 + u16 dlen; 53 + }; 54 + 55 + struct buf_ptr { 56 + u8 *vptr; 57 + dma_addr_t dma_addr; 58 + u16 size; 59 + }; 60 + 61 + struct cpt_request_info { 62 + u8 incnt; /* Number of input buffers */ 63 + u8 outcnt; /* Number of output buffers */ 64 + u16 rlen; /* Output length */ 65 + union ctrl_info ctrl; /* User control information */ 66 + struct cptvf_request req; /* Request Information (Core specific) */ 67 + 68 + struct buf_ptr in[MAX_BUF_CNT]; 69 + struct buf_ptr out[MAX_BUF_CNT]; 70 + 71 + void (*callback)(int, void *); /* Kernel ASYNC request callabck */ 72 + void *callback_arg; /* Kernel ASYNC request callabck arg */ 73 + }; 74 + 75 + struct sglist_component { 76 + union { 77 + u64 len; 78 + struct { 79 + u16 len0; 80 + u16 len1; 81 + u16 len2; 82 + u16 len3; 83 + } s; 84 + } u; 85 + u64 ptr0; 86 + u64 ptr1; 87 + u64 ptr2; 88 + u64 ptr3; 89 + }; 90 + 91 + struct cpt_info_buffer { 92 + struct cpt_vf *cptvf; 93 + unsigned long time_in; 94 + u8 extra_time; 95 + 96 + struct cpt_request_info *req; 97 + dma_addr_t dptr_baddr; 98 + u32 dlen; 99 + dma_addr_t rptr_baddr; 100 + dma_addr_t comp_baddr; 101 + u8 *in_buffer; 102 + u8 *out_buffer; 103 + u8 *gather_components; 104 + u8 *scatter_components; 105 + 106 + struct pending_entry *pentry; 107 + volatile u64 *completion_addr; 108 + volatile u64 *alternate_caddr; 109 + }; 110 + 111 + /* 112 + * CPT_INST_S software command definitions 113 + * Words EI (0-3) 114 + */ 115 + union vq_cmd_word0 { 116 + u64 u64; 117 + struct { 118 + u16 opcode; 119 + u16 param1; 120 + u16 param2; 121 + u16 dlen; 122 + } s; 123 + }; 124 + 125 + union vq_cmd_word3 { 126 + u64 u64; 127 + struct { 128 + #if defined(__BIG_ENDIAN_BITFIELD) 129 + u64 grp:3; 130 + u64 cptr:61; 131 + #else 132 + u64 cptr:61; 133 + u64 grp:3; 134 + #endif 135 + } s; 136 + }; 137 + 138 + struct cpt_vq_command { 139 + union vq_cmd_word0 cmd; 140 + u64 dptr; 141 + u64 rptr; 142 + union vq_cmd_word3 cptr; 143 + }; 144 + 145 + void vq_post_process(struct cpt_vf *cptvf, u32 qno); 146 + int process_request(struct cpt_vf *cptvf, struct cpt_request_info *req); 147 + #endif /* __REQUEST_MANAGER_H */