int cc_map_aead_request()

in ccree/cc_buffer_mgr.c [937:1129]


int cc_map_aead_request(struct cc_drvdata *drvdata, struct aead_request *req)
{
	struct aead_req_ctx *areq_ctx = aead_request_ctx(req);
	struct mlli_params *mlli_params = &areq_ctx->mlli_params;
	struct device *dev = drvdata_to_dev(drvdata);
	struct buffer_array sg_data;
	unsigned int authsize = areq_ctx->req_authsize;
	int rc = 0;
	dma_addr_t dma_addr;
	u32 mapped_nents = 0;
	u32 dummy = 0; /*used for the assoc data fragments */
	u32 size_to_map;
	gfp_t flags = cc_gfp_flags(&req->base);

	mlli_params->curr_pool = NULL;
	sg_data.num_of_buffers = 0;

	/* copy mac to a temporary location to deal with possible
	 * data memory overriding that caused by cache coherence problem.
	 */
	if (drvdata->coherent &&
	    areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_DECRYPT &&
	    req->src == req->dst)
		cc_copy_mac(dev, req, CC_SG_TO_BUF);

	/* cacluate the size for cipher remove ICV in decrypt*/
	areq_ctx->cryptlen = (areq_ctx->gen_ctx.op_type ==
				 DRV_CRYPTO_DIRECTION_ENCRYPT) ?
				req->cryptlen :
				(req->cryptlen - authsize);

	dma_addr = dma_map_single(dev, areq_ctx->mac_buf, MAX_MAC_SIZE,
				  DMA_BIDIRECTIONAL);
	if (dma_mapping_error(dev, dma_addr)) {
		dev_err(dev, "Mapping mac_buf %u B at va=%pK for DMA failed\n",
			MAX_MAC_SIZE, areq_ctx->mac_buf);
		rc = -ENOMEM;
		goto aead_map_failure;
	}
	areq_ctx->mac_buf_dma_addr = dma_addr;

	if (areq_ctx->ccm_hdr_size != ccm_header_size_null) {
		void *addr = areq_ctx->ccm_config + CCM_CTR_COUNT_0_OFFSET;

		dma_addr = dma_map_single(dev, addr, AES_BLOCK_SIZE,
					  DMA_TO_DEVICE);

		if (dma_mapping_error(dev, dma_addr)) {
			dev_err(dev, "Mapping mac_buf %u B at va=%pK for DMA failed\n",
				AES_BLOCK_SIZE, addr);
			areq_ctx->ccm_iv0_dma_addr = 0;
			rc = -ENOMEM;
			goto aead_map_failure;
		}
		areq_ctx->ccm_iv0_dma_addr = dma_addr;

		rc = cc_set_aead_conf_buf(dev, areq_ctx, areq_ctx->ccm_config,
					  &sg_data, areq_ctx->assoclen);
		if (rc)
			goto aead_map_failure;
	}

	if (areq_ctx->cipher_mode == DRV_CIPHER_GCTR) {
		dma_addr = dma_map_single(dev, areq_ctx->hkey, AES_BLOCK_SIZE,
					  DMA_BIDIRECTIONAL);
		if (dma_mapping_error(dev, dma_addr)) {
			dev_err(dev, "Mapping hkey %u B at va=%pK for DMA failed\n",
				AES_BLOCK_SIZE, areq_ctx->hkey);
			rc = -ENOMEM;
			goto aead_map_failure;
		}
		areq_ctx->hkey_dma_addr = dma_addr;

		dma_addr = dma_map_single(dev, &areq_ctx->gcm_len_block,
					  AES_BLOCK_SIZE, DMA_TO_DEVICE);
		if (dma_mapping_error(dev, dma_addr)) {
			dev_err(dev, "Mapping gcm_len_block %u B at va=%pK for DMA failed\n",
				AES_BLOCK_SIZE, &areq_ctx->gcm_len_block);
			rc = -ENOMEM;
			goto aead_map_failure;
		}
		areq_ctx->gcm_block_len_dma_addr = dma_addr;

		dma_addr = dma_map_single(dev, areq_ctx->gcm_iv_inc1,
					  AES_BLOCK_SIZE, DMA_TO_DEVICE);

		if (dma_mapping_error(dev, dma_addr)) {
			dev_err(dev, "Mapping gcm_iv_inc1 %u B at va=%pK for DMA failed\n",
				AES_BLOCK_SIZE, (areq_ctx->gcm_iv_inc1));
			areq_ctx->gcm_iv_inc1_dma_addr = 0;
			rc = -ENOMEM;
			goto aead_map_failure;
		}
		areq_ctx->gcm_iv_inc1_dma_addr = dma_addr;

		dma_addr = dma_map_single(dev, areq_ctx->gcm_iv_inc2,
					  AES_BLOCK_SIZE, DMA_TO_DEVICE);

		if (dma_mapping_error(dev, dma_addr)) {
			dev_err(dev, "Mapping gcm_iv_inc2 %u B at va=%pK for DMA failed\n",
				AES_BLOCK_SIZE, (areq_ctx->gcm_iv_inc2));
			areq_ctx->gcm_iv_inc2_dma_addr = 0;
			rc = -ENOMEM;
			goto aead_map_failure;
		}
		areq_ctx->gcm_iv_inc2_dma_addr = dma_addr;
	}

	size_to_map = req->cryptlen + req->assoclen;
	/* If we do in-place encryption, we also need the auth tag */
	if ((areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_ENCRYPT) &&
	   (req->src == req->dst)) {
		size_to_map += authsize;
	}

	rc = cc_map_sg(dev, req->src, size_to_map, DMA_BIDIRECTIONAL,
		       &areq_ctx->src.mapped_nents,
		       (LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES +
			LLI_MAX_NUM_OF_DATA_ENTRIES),
		       &dummy, &mapped_nents);
	if (rc)
		goto aead_map_failure;

	if (areq_ctx->is_single_pass) {
		/*
		 * Create MLLI table for:
		 *   (1) Assoc. data
		 *   (2) Src/Dst SGLs
		 *   Note: IV is contg. buffer (not an SGL)
		 */
		rc = cc_aead_chain_assoc(drvdata, req, &sg_data, true, false);
		if (rc)
			goto aead_map_failure;
		rc = cc_aead_chain_iv(drvdata, req, &sg_data, true, false);
		if (rc)
			goto aead_map_failure;
		rc = cc_aead_chain_data(drvdata, req, &sg_data, true, false);
		if (rc)
			goto aead_map_failure;
	} else { /* DOUBLE-PASS flow */
		/*
		 * Prepare MLLI table(s) in this order:
		 *
		 * If ENCRYPT/DECRYPT (inplace):
		 *   (1) MLLI table for assoc
		 *   (2) IV entry (chained right after end of assoc)
		 *   (3) MLLI for src/dst (inplace operation)
		 *
		 * If ENCRYPT (non-inplace)
		 *   (1) MLLI table for assoc
		 *   (2) IV entry (chained right after end of assoc)
		 *   (3) MLLI for dst
		 *   (4) MLLI for src
		 *
		 * If DECRYPT (non-inplace)
		 *   (1) MLLI table for assoc
		 *   (2) IV entry (chained right after end of assoc)
		 *   (3) MLLI for src
		 *   (4) MLLI for dst
		 */
		rc = cc_aead_chain_assoc(drvdata, req, &sg_data, false, true);
		if (rc)
			goto aead_map_failure;
		rc = cc_aead_chain_iv(drvdata, req, &sg_data, false, true);
		if (rc)
			goto aead_map_failure;
		rc = cc_aead_chain_data(drvdata, req, &sg_data, true, true);
		if (rc)
			goto aead_map_failure;
	}

	/* Mlli support -start building the MLLI according to the above
	 * results
	 */
	if (areq_ctx->assoc_buff_type == CC_DMA_BUF_MLLI ||
	    areq_ctx->data_buff_type == CC_DMA_BUF_MLLI) {
		mlli_params->curr_pool = drvdata->mlli_buffs_pool;
		rc = cc_generate_mlli(dev, &sg_data, mlli_params, flags);
		if (rc)
			goto aead_map_failure;

		cc_update_aead_mlli_nents(drvdata, req);
		dev_dbg(dev, "assoc params mn %d\n",
			areq_ctx->assoc.mlli_nents);
		dev_dbg(dev, "src params mn %d\n", areq_ctx->src.mlli_nents);
		dev_dbg(dev, "dst params mn %d\n", areq_ctx->dst.mlli_nents);
	}
	return 0;

aead_map_failure:
	cc_unmap_aead_request(dev, req);
	return rc;
}