You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
crypto: ccp - Register the CCP as a DMA resource
The CCP has the ability to provide DMA services to the kernel using pass-through mode of the device. Register these services as general purpose DMA channels. Changes since v2: - Add a Signed-off-by Changes since v1: - Allocate memory for a string in ccp_dmaengine_register - Ensure register/unregister calls are properly ordered - Verified all changed files are listed in the diffstat - Undo some superfluous changes - Added a cc: Signed-off-by: Gary R Hook <gary.hook@amd.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
@@ -3,6 +3,7 @@ config CRYPTO_DEV_CCP_DD
|
||||
depends on CRYPTO_DEV_CCP
|
||||
default m
|
||||
select HW_RANDOM
|
||||
select DMA_ENGINE
|
||||
select CRYPTO_SHA1
|
||||
select CRYPTO_SHA256
|
||||
help
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
obj-$(CONFIG_CRYPTO_DEV_CCP_DD) += ccp.o
|
||||
ccp-objs := ccp-dev.o ccp-ops.o ccp-dev-v3.o ccp-platform.o
|
||||
ccp-objs := ccp-dev.o \
|
||||
ccp-ops.o \
|
||||
ccp-dev-v3.o \
|
||||
ccp-platform.o \
|
||||
ccp-dmaengine.o
|
||||
ccp-$(CONFIG_PCI) += ccp-pci.o
|
||||
|
||||
obj-$(CONFIG_CRYPTO_DEV_CCP_CRYPTO) += ccp-crypto.o
|
||||
|
||||
@@ -406,6 +406,11 @@ static int ccp_init(struct ccp_device *ccp)
|
||||
goto e_kthread;
|
||||
}
|
||||
|
||||
/* Register the DMA engine support */
|
||||
ret = ccp_dmaengine_register(ccp);
|
||||
if (ret)
|
||||
goto e_hwrng;
|
||||
|
||||
ccp_add_device(ccp);
|
||||
|
||||
/* Enable interrupts */
|
||||
@@ -413,6 +418,9 @@ static int ccp_init(struct ccp_device *ccp)
|
||||
|
||||
return 0;
|
||||
|
||||
e_hwrng:
|
||||
hwrng_unregister(&ccp->hwrng);
|
||||
|
||||
e_kthread:
|
||||
for (i = 0; i < ccp->cmd_q_count; i++)
|
||||
if (ccp->cmd_q[i].kthread)
|
||||
@@ -436,6 +444,9 @@ static void ccp_destroy(struct ccp_device *ccp)
|
||||
/* Remove this device from the list of available units first */
|
||||
ccp_del_device(ccp);
|
||||
|
||||
/* Unregister the DMA engine */
|
||||
ccp_dmaengine_unregister(ccp);
|
||||
|
||||
/* Unregister the RNG */
|
||||
hwrng_unregister(&ccp->hwrng);
|
||||
|
||||
|
||||
@@ -22,6 +22,9 @@
|
||||
#include <linux/dmapool.h>
|
||||
#include <linux/hw_random.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irqreturn.h>
|
||||
#include <linux/dmaengine.h>
|
||||
|
||||
#define MAX_CCP_NAME_LEN 16
|
||||
#define MAX_DMAPOOL_NAME_LEN 32
|
||||
@@ -167,6 +170,39 @@ extern struct ccp_vdata ccpv3;
|
||||
struct ccp_device;
|
||||
struct ccp_cmd;
|
||||
|
||||
struct ccp_dma_cmd {
|
||||
struct list_head entry;
|
||||
|
||||
struct ccp_cmd ccp_cmd;
|
||||
};
|
||||
|
||||
struct ccp_dma_desc {
|
||||
struct list_head entry;
|
||||
|
||||
struct ccp_device *ccp;
|
||||
|
||||
struct list_head pending;
|
||||
struct list_head active;
|
||||
|
||||
enum dma_status status;
|
||||
struct dma_async_tx_descriptor tx_desc;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
struct ccp_dma_chan {
|
||||
struct ccp_device *ccp;
|
||||
|
||||
spinlock_t lock;
|
||||
struct list_head pending;
|
||||
struct list_head active;
|
||||
struct list_head complete;
|
||||
|
||||
struct tasklet_struct cleanup_tasklet;
|
||||
|
||||
enum dma_status status;
|
||||
struct dma_chan dma_chan;
|
||||
};
|
||||
|
||||
struct ccp_cmd_queue {
|
||||
struct ccp_device *ccp;
|
||||
|
||||
@@ -260,6 +296,14 @@ struct ccp_device {
|
||||
struct hwrng hwrng;
|
||||
unsigned int hwrng_retries;
|
||||
|
||||
/*
|
||||
* Support for the CCP DMA capabilities
|
||||
*/
|
||||
struct dma_device dma_dev;
|
||||
struct ccp_dma_chan *ccp_dma_chan;
|
||||
struct kmem_cache *dma_cmd_cache;
|
||||
struct kmem_cache *dma_desc_cache;
|
||||
|
||||
/*
|
||||
* A counter used to generate job-ids for cmds submitted to the CCP
|
||||
*/
|
||||
@@ -418,4 +462,7 @@ int ccp_cmd_queue_thread(void *data);
|
||||
|
||||
int ccp_run_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd);
|
||||
|
||||
int ccp_dmaengine_register(struct ccp_device *ccp);
|
||||
void ccp_dmaengine_unregister(struct ccp_device *ccp);
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1427,6 +1427,70 @@ e_mask:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ccp_run_passthru_nomap_cmd(struct ccp_cmd_queue *cmd_q,
|
||||
struct ccp_cmd *cmd)
|
||||
{
|
||||
struct ccp_passthru_nomap_engine *pt = &cmd->u.passthru_nomap;
|
||||
struct ccp_dm_workarea mask;
|
||||
struct ccp_op op;
|
||||
int ret;
|
||||
|
||||
if (!pt->final && (pt->src_len & (CCP_PASSTHRU_BLOCKSIZE - 1)))
|
||||
return -EINVAL;
|
||||
|
||||
if (!pt->src_dma || !pt->dst_dma)
|
||||
return -EINVAL;
|
||||
|
||||
if (pt->bit_mod != CCP_PASSTHRU_BITWISE_NOOP) {
|
||||
if (pt->mask_len != CCP_PASSTHRU_MASKSIZE)
|
||||
return -EINVAL;
|
||||
if (!pt->mask)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
BUILD_BUG_ON(CCP_PASSTHRU_KSB_COUNT != 1);
|
||||
|
||||
memset(&op, 0, sizeof(op));
|
||||
op.cmd_q = cmd_q;
|
||||
op.jobid = ccp_gen_jobid(cmd_q->ccp);
|
||||
|
||||
if (pt->bit_mod != CCP_PASSTHRU_BITWISE_NOOP) {
|
||||
/* Load the mask */
|
||||
op.ksb_key = cmd_q->ksb_key;
|
||||
|
||||
mask.length = pt->mask_len;
|
||||
mask.dma.address = pt->mask;
|
||||
mask.dma.length = pt->mask_len;
|
||||
|
||||
ret = ccp_copy_to_ksb(cmd_q, &mask, op.jobid, op.ksb_key,
|
||||
CCP_PASSTHRU_BYTESWAP_NOOP);
|
||||
if (ret) {
|
||||
cmd->engine_error = cmd_q->cmd_error;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Send data to the CCP Passthru engine */
|
||||
op.eom = 1;
|
||||
op.soc = 1;
|
||||
|
||||
op.src.type = CCP_MEMTYPE_SYSTEM;
|
||||
op.src.u.dma.address = pt->src_dma;
|
||||
op.src.u.dma.offset = 0;
|
||||
op.src.u.dma.length = pt->src_len;
|
||||
|
||||
op.dst.type = CCP_MEMTYPE_SYSTEM;
|
||||
op.dst.u.dma.address = pt->dst_dma;
|
||||
op.dst.u.dma.offset = 0;
|
||||
op.dst.u.dma.length = pt->src_len;
|
||||
|
||||
ret = cmd_q->ccp->vdata->perform->perform_passthru(&op);
|
||||
if (ret)
|
||||
cmd->engine_error = cmd_q->cmd_error;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ccp_run_ecc_mm_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd)
|
||||
{
|
||||
struct ccp_ecc_engine *ecc = &cmd->u.ecc;
|
||||
@@ -1762,7 +1826,10 @@ int ccp_run_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd)
|
||||
ret = ccp_run_rsa_cmd(cmd_q, cmd);
|
||||
break;
|
||||
case CCP_ENGINE_PASSTHRU:
|
||||
ret = ccp_run_passthru_cmd(cmd_q, cmd);
|
||||
if (cmd->flags & CCP_CMD_PASSTHRU_NO_DMA_MAP)
|
||||
ret = ccp_run_passthru_nomap_cmd(cmd_q, cmd);
|
||||
else
|
||||
ret = ccp_run_passthru_cmd(cmd_q, cmd);
|
||||
break;
|
||||
case CCP_ENGINE_ECC:
|
||||
ret = ccp_run_ecc_cmd(cmd_q, cmd);
|
||||
|
||||
+34
-2
@@ -1,9 +1,10 @@
|
||||
/*
|
||||
* AMD Cryptographic Coprocessor (CCP) driver
|
||||
*
|
||||
* Copyright (C) 2013 Advanced Micro Devices, Inc.
|
||||
* Copyright (C) 2013,2016 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Author: Tom Lendacky <thomas.lendacky@amd.com>
|
||||
* Author: Gary R Hook <gary.hook@amd.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@@ -381,6 +382,35 @@ struct ccp_passthru_engine {
|
||||
u32 final;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ccp_passthru_nomap_engine - CCP pass-through operation
|
||||
* without performing DMA mapping
|
||||
* @bit_mod: bitwise operation to perform
|
||||
* @byte_swap: byteswap operation to perform
|
||||
* @mask: mask to be applied to data
|
||||
* @mask_len: length in bytes of mask
|
||||
* @src: data to be used for this operation
|
||||
* @dst: data produced by this operation
|
||||
* @src_len: length in bytes of data used for this operation
|
||||
* @final: indicate final pass-through operation
|
||||
*
|
||||
* Variables required to be set when calling ccp_enqueue_cmd():
|
||||
* - bit_mod, byte_swap, src, dst, src_len
|
||||
* - mask, mask_len if bit_mod is not CCP_PASSTHRU_BITWISE_NOOP
|
||||
*/
|
||||
struct ccp_passthru_nomap_engine {
|
||||
enum ccp_passthru_bitwise bit_mod;
|
||||
enum ccp_passthru_byteswap byte_swap;
|
||||
|
||||
dma_addr_t mask;
|
||||
u32 mask_len; /* In bytes */
|
||||
|
||||
dma_addr_t src_dma, dst_dma;
|
||||
u64 src_len; /* In bytes */
|
||||
|
||||
u32 final;
|
||||
};
|
||||
|
||||
/***** ECC engine *****/
|
||||
#define CCP_ECC_MODULUS_BYTES 48 /* 384-bits */
|
||||
#define CCP_ECC_MAX_OPERANDS 6
|
||||
@@ -522,7 +552,8 @@ enum ccp_engine {
|
||||
};
|
||||
|
||||
/* Flag values for flags member of ccp_cmd */
|
||||
#define CCP_CMD_MAY_BACKLOG 0x00000001
|
||||
#define CCP_CMD_MAY_BACKLOG 0x00000001
|
||||
#define CCP_CMD_PASSTHRU_NO_DMA_MAP 0x00000002
|
||||
|
||||
/**
|
||||
* struct ccp_cmd - CPP operation request
|
||||
@@ -562,6 +593,7 @@ struct ccp_cmd {
|
||||
struct ccp_sha_engine sha;
|
||||
struct ccp_rsa_engine rsa;
|
||||
struct ccp_passthru_engine passthru;
|
||||
struct ccp_passthru_nomap_engine passthru_nomap;
|
||||
struct ccp_ecc_engine ecc;
|
||||
} u;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user