drivers/crypto/marvell/octeontx2/otx2_cptvf_algs.c

Source file repositories/reference/linux-study-clean/drivers/crypto/marvell/octeontx2/otx2_cptvf_algs.c

File Facts

System
Linux kernel
Corpus path
drivers/crypto/marvell/octeontx2/otx2_cptvf_algs.c
Extension
.c
Size
46187 bytes
Lines
1701
Domain
Driver Families
Bucket
drivers/crypto
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct cpt_device_desc {
	struct pci_dev *dev;
	int num_queues;
};

struct cpt_device_table {
	atomic_t count;
	struct cpt_device_desc desc[OTX2_CPT_MAX_LFS_NUM];
};

static struct cpt_device_table se_devices = {
	.count = ATOMIC_INIT(0)
};

static struct otx2_cpt_sdesc *alloc_sdesc(struct crypto_shash *alg);

static inline int get_se_device(struct pci_dev **pdev, int *cpu_num)
{
	int count;

	count = atomic_read(&se_devices.count);
	if (count < 1)
		return -ENODEV;

	*cpu_num = get_cpu();
	/*
	 * On OcteonTX2 platform CPT instruction queue is bound to each
	 * local function LF, in turn LFs can be attached to PF
	 * or VF therefore we always use first device. We get maximum
	 * performance if one CPT queue is available for each cpu
	 * otherwise CPT queues need to be shared between cpus.
	 */
	if (*cpu_num >= se_devices.desc[0].num_queues)
		*cpu_num %= se_devices.desc[0].num_queues;
	*pdev = se_devices.desc[0].dev;

	put_cpu();

	return 0;
}

static inline int validate_hmac_cipher_null(struct otx2_cpt_req_info *cpt_req)
{
	struct otx2_cpt_req_ctx *rctx;
	struct aead_request *req;
	struct crypto_aead *tfm;

	req = container_of(cpt_req->areq, struct aead_request, base);
	tfm = crypto_aead_reqtfm(req);
	rctx = aead_request_ctx_dma(req);
	if (memcmp(rctx->fctx.hmac.s.hmac_calc,
		   rctx->fctx.hmac.s.hmac_recv,
		   crypto_aead_authsize(tfm)) != 0)
		return -EBADMSG;

	return 0;
}

static void otx2_cpt_aead_callback(int status, void *arg1, void *arg2)
{
	struct otx2_cpt_inst_info *inst_info = arg2;
	struct crypto_async_request *areq = arg1;
	struct otx2_cpt_req_info *cpt_req;
	struct pci_dev *pdev;

	if (inst_info) {
		cpt_req = inst_info->req;
		if (!status) {
			/*
			 * When selected cipher is NULL we need to manually
			 * verify whether calculated hmac value matches
			 * received hmac value
			 */
			if (cpt_req->req_type ==
			    OTX2_CPT_AEAD_ENC_DEC_NULL_REQ &&
			    !cpt_req->is_enc)
				status = validate_hmac_cipher_null(cpt_req);
		}
		pdev = inst_info->pdev;
		otx2_cpt_info_destroy(pdev, inst_info);
	}
	if (areq)
		crypto_request_complete(areq, status);
}

static void output_iv_copyback(struct crypto_async_request *areq)
{
	struct otx2_cpt_req_info *req_info;
	struct otx2_cpt_req_ctx *rctx;
	struct skcipher_request *sreq;

Annotation

Implementation Notes