Commit 58ea8abf authored by Gary R Hook's avatar Gary R Hook Committed by Herbert Xu

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: default avatarGary R Hook <gary.hook@amd.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 5343e674
...@@ -3,6 +3,7 @@ config CRYPTO_DEV_CCP_DD ...@@ -3,6 +3,7 @@ config CRYPTO_DEV_CCP_DD
depends on CRYPTO_DEV_CCP depends on CRYPTO_DEV_CCP
default m default m
select HW_RANDOM select HW_RANDOM
select DMA_ENGINE
select CRYPTO_SHA1 select CRYPTO_SHA1
select CRYPTO_SHA256 select CRYPTO_SHA256
help help
......
obj-$(CONFIG_CRYPTO_DEV_CCP_DD) += ccp.o 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 ccp-$(CONFIG_PCI) += ccp-pci.o
obj-$(CONFIG_CRYPTO_DEV_CCP_CRYPTO) += ccp-crypto.o obj-$(CONFIG_CRYPTO_DEV_CCP_CRYPTO) += ccp-crypto.o
......
...@@ -406,6 +406,11 @@ static int ccp_init(struct ccp_device *ccp) ...@@ -406,6 +406,11 @@ static int ccp_init(struct ccp_device *ccp)
goto e_kthread; goto e_kthread;
} }
/* Register the DMA engine support */
ret = ccp_dmaengine_register(ccp);
if (ret)
goto e_hwrng;
ccp_add_device(ccp); ccp_add_device(ccp);
/* Enable interrupts */ /* Enable interrupts */
...@@ -413,6 +418,9 @@ static int ccp_init(struct ccp_device *ccp) ...@@ -413,6 +418,9 @@ static int ccp_init(struct ccp_device *ccp)
return 0; return 0;
e_hwrng:
hwrng_unregister(&ccp->hwrng);
e_kthread: e_kthread:
for (i = 0; i < ccp->cmd_q_count; i++) for (i = 0; i < ccp->cmd_q_count; i++)
if (ccp->cmd_q[i].kthread) if (ccp->cmd_q[i].kthread)
...@@ -436,6 +444,9 @@ static void ccp_destroy(struct ccp_device *ccp) ...@@ -436,6 +444,9 @@ static void ccp_destroy(struct ccp_device *ccp)
/* Remove this device from the list of available units first */ /* Remove this device from the list of available units first */
ccp_del_device(ccp); ccp_del_device(ccp);
/* Unregister the DMA engine */
ccp_dmaengine_unregister(ccp);
/* Unregister the RNG */ /* Unregister the RNG */
hwrng_unregister(&ccp->hwrng); hwrng_unregister(&ccp->hwrng);
......
...@@ -22,6 +22,9 @@ ...@@ -22,6 +22,9 @@
#include <linux/dmapool.h> #include <linux/dmapool.h>
#include <linux/hw_random.h> #include <linux/hw_random.h>
#include <linux/bitops.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_CCP_NAME_LEN 16
#define MAX_DMAPOOL_NAME_LEN 32 #define MAX_DMAPOOL_NAME_LEN 32
...@@ -167,6 +170,39 @@ extern struct ccp_vdata ccpv3; ...@@ -167,6 +170,39 @@ extern struct ccp_vdata ccpv3;
struct ccp_device; struct ccp_device;
struct ccp_cmd; 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_cmd_queue {
struct ccp_device *ccp; struct ccp_device *ccp;
...@@ -260,6 +296,14 @@ struct ccp_device { ...@@ -260,6 +296,14 @@ struct ccp_device {
struct hwrng hwrng; struct hwrng hwrng;
unsigned int hwrng_retries; 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 * A counter used to generate job-ids for cmds submitted to the CCP
*/ */
...@@ -418,4 +462,7 @@ int ccp_cmd_queue_thread(void *data); ...@@ -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_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 #endif
This diff is collapsed.
...@@ -1427,6 +1427,70 @@ static int ccp_run_passthru_cmd(struct ccp_cmd_queue *cmd_q, ...@@ -1427,6 +1427,70 @@ static int ccp_run_passthru_cmd(struct ccp_cmd_queue *cmd_q,
return ret; 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) 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; 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) ...@@ -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); ret = ccp_run_rsa_cmd(cmd_q, cmd);
break; break;
case CCP_ENGINE_PASSTHRU: 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; break;
case CCP_ENGINE_ECC: case CCP_ENGINE_ECC:
ret = ccp_run_ecc_cmd(cmd_q, cmd); ret = ccp_run_ecc_cmd(cmd_q, cmd);
......
/* /*
* AMD Cryptographic Coprocessor (CCP) driver * 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: 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 * 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 * it under the terms of the GNU General Public License version 2 as
...@@ -381,6 +382,35 @@ struct ccp_passthru_engine { ...@@ -381,6 +382,35 @@ struct ccp_passthru_engine {
u32 final; 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 *****/ /***** ECC engine *****/
#define CCP_ECC_MODULUS_BYTES 48 /* 384-bits */ #define CCP_ECC_MODULUS_BYTES 48 /* 384-bits */
#define CCP_ECC_MAX_OPERANDS 6 #define CCP_ECC_MAX_OPERANDS 6
...@@ -522,7 +552,8 @@ enum ccp_engine { ...@@ -522,7 +552,8 @@ enum ccp_engine {
}; };
/* Flag values for flags member of ccp_cmd */ /* 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 * struct ccp_cmd - CPP operation request
...@@ -562,6 +593,7 @@ struct ccp_cmd { ...@@ -562,6 +593,7 @@ struct ccp_cmd {
struct ccp_sha_engine sha; struct ccp_sha_engine sha;
struct ccp_rsa_engine rsa; struct ccp_rsa_engine rsa;
struct ccp_passthru_engine passthru; struct ccp_passthru_engine passthru;
struct ccp_passthru_nomap_engine passthru_nomap;
struct ccp_ecc_engine ecc; struct ccp_ecc_engine ecc;
} u; } u;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment