Commit 67c2315d authored by Horia Geantă's avatar Horia Geantă Committed by Herbert Xu

crypto: caam - add Queue Interface (QI) backend support

CAAM engine supports two interfaces for crypto job submission:
-job ring interface - already existing caam/jr driver
-Queue Interface (QI) - caam/qi driver added in current patch

QI is present in CAAM engines found on DPAA platforms.
QI gets its I/O (frame descriptors) from QMan (Queue Manager) queues.

This patch adds a platform device for accessing CAAM's queue interface.
The requests are submitted to CAAM using one frame queue per
cryptographic context. Each crypto context has one shared descriptor.
This shared descriptor is attached to frame queue associated with
corresponding driver context using context_a.

The driver hides the mechanics of FQ creation, initialisation from its
applications. Each cryptographic context needs to be associated with
driver context which houses the FQ to be used to transport the job to
CAAM. The driver provides API for:
(a) Context creation
(b) Job submission
(c) Context deletion
(d) Congestion indication - whether path to/from CAAM is congested

The driver supports affining its context to a particular CPU.
This means that any responses from CAAM for the context in question
would arrive at the given CPU. This helps in implementing one CPU
per packet round trip in IPsec application.

The driver processes CAAM responses under NAPI contexts.
NAPI contexts are instantiated only on cores with affined portals since
only cores having their own portal can receive responses from DQRR.

The responses from CAAM for all cryptographic contexts ride on a fixed
set of FQs. We use one response FQ per portal owning core. The response
FQ is configured in each core's and thus portal's dedicated channel.
This gives the flexibility to direct CAAM's responses for a crypto
context on a given core.
Signed-off-by: default avatarVakul Garg <vakul.garg@nxp.com>
Signed-off-by: default avatarAlex Porosanu <alexandru.porosanu@nxp.com>
Signed-off-by: default avatarHoria Geantă <horia.geanta@nxp.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent cd373691
...@@ -16,3 +16,7 @@ obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_PKC_API) += caam_pkc.o ...@@ -16,3 +16,7 @@ obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_PKC_API) += caam_pkc.o
caam-objs := ctrl.o caam-objs := ctrl.o
caam_jr-objs := jr.o key_gen.o error.o caam_jr-objs := jr.o key_gen.o error.o
caam_pkc-y := caampkc.o pkc_desc.o caam_pkc-y := caampkc.o pkc_desc.o
ifneq ($(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI),)
ccflags-y += -DCONFIG_CAAM_QI
caam-objs += qi.o
endif
...@@ -18,6 +18,10 @@ ...@@ -18,6 +18,10 @@
bool caam_little_end; bool caam_little_end;
EXPORT_SYMBOL(caam_little_end); EXPORT_SYMBOL(caam_little_end);
#ifdef CONFIG_CAAM_QI
#include "qi.h"
#endif
/* /*
* i.MX targets tend to have clock control subsystems that can * i.MX targets tend to have clock control subsystems that can
* enable/disable clocking to our device. * enable/disable clocking to our device.
...@@ -311,6 +315,11 @@ static int caam_remove(struct platform_device *pdev) ...@@ -311,6 +315,11 @@ static int caam_remove(struct platform_device *pdev)
for (ring = 0; ring < ctrlpriv->total_jobrs; ring++) for (ring = 0; ring < ctrlpriv->total_jobrs; ring++)
of_device_unregister(ctrlpriv->jrpdev[ring]); of_device_unregister(ctrlpriv->jrpdev[ring]);
#ifdef CONFIG_CAAM_QI
if (ctrlpriv->qidev)
caam_qi_shutdown(ctrlpriv->qidev);
#endif
/* De-initialize RNG state handles initialized by this driver. */ /* De-initialize RNG state handles initialized by this driver. */
if (ctrlpriv->rng4_sh_init) if (ctrlpriv->rng4_sh_init)
deinstantiate_rng(ctrldev, ctrlpriv->rng4_sh_init); deinstantiate_rng(ctrldev, ctrlpriv->rng4_sh_init);
...@@ -401,23 +410,6 @@ int caam_get_era(void) ...@@ -401,23 +410,6 @@ int caam_get_era(void)
} }
EXPORT_SYMBOL(caam_get_era); EXPORT_SYMBOL(caam_get_era);
#ifdef CONFIG_DEBUG_FS
static int caam_debugfs_u64_get(void *data, u64 *val)
{
*val = caam64_to_cpu(*(u64 *)data);
return 0;
}
static int caam_debugfs_u32_get(void *data, u64 *val)
{
*val = caam32_to_cpu(*(u32 *)data);
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(caam_fops_u32_ro, caam_debugfs_u32_get, NULL, "%llu\n");
DEFINE_SIMPLE_ATTRIBUTE(caam_fops_u64_ro, caam_debugfs_u64_get, NULL, "%llu\n");
#endif
/* Probe routine for CAAM top (controller) level */ /* Probe routine for CAAM top (controller) level */
static int caam_probe(struct platform_device *pdev) static int caam_probe(struct platform_device *pdev)
{ {
...@@ -615,6 +607,17 @@ static int caam_probe(struct platform_device *pdev) ...@@ -615,6 +607,17 @@ static int caam_probe(struct platform_device *pdev)
goto iounmap_ctrl; goto iounmap_ctrl;
} }
#ifdef CONFIG_DEBUG_FS
/*
* FIXME: needs better naming distinction, as some amalgamation of
* "caam" and nprop->full_name. The OF name isn't distinctive,
* but does separate instances
*/
perfmon = (struct caam_perfmon __force *)&ctrl->perfmon;
ctrlpriv->dfs_root = debugfs_create_dir(dev_name(dev), NULL);
ctrlpriv->ctl = debugfs_create_dir("ctl", ctrlpriv->dfs_root);
#endif
ring = 0; ring = 0;
ridx = 0; ridx = 0;
ctrlpriv->total_jobrs = 0; ctrlpriv->total_jobrs = 0;
...@@ -650,6 +653,13 @@ static int caam_probe(struct platform_device *pdev) ...@@ -650,6 +653,13 @@ static int caam_probe(struct platform_device *pdev)
); );
/* This is all that's required to physically enable QI */ /* This is all that's required to physically enable QI */
wr_reg32(&ctrlpriv->qi->qi_control_lo, QICTL_DQEN); wr_reg32(&ctrlpriv->qi->qi_control_lo, QICTL_DQEN);
/* If QMAN driver is present, init CAAM-QI backend */
#ifdef CONFIG_CAAM_QI
ret = caam_qi_init(pdev);
if (ret)
dev_err(dev, "caam qi i/f init failed: %d\n", ret);
#endif
} }
/* If no QI and no rings specified, quit and go home */ /* If no QI and no rings specified, quit and go home */
...@@ -737,17 +747,6 @@ static int caam_probe(struct platform_device *pdev) ...@@ -737,17 +747,6 @@ static int caam_probe(struct platform_device *pdev)
ctrlpriv->total_jobrs, ctrlpriv->qi_present); ctrlpriv->total_jobrs, ctrlpriv->qi_present);
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
/*
* FIXME: needs better naming distinction, as some amalgamation of
* "caam" and nprop->full_name. The OF name isn't distinctive,
* but does separate instances
*/
perfmon = (struct caam_perfmon __force *)&ctrl->perfmon;
ctrlpriv->dfs_root = debugfs_create_dir(dev_name(dev), NULL);
ctrlpriv->ctl = debugfs_create_dir("ctl", ctrlpriv->dfs_root);
/* Controller-level - performance monitor counters */
ctrlpriv->ctl_rq_dequeued = ctrlpriv->ctl_rq_dequeued =
debugfs_create_file("rq_dequeued", debugfs_create_file("rq_dequeued",
...@@ -830,6 +829,9 @@ static int caam_probe(struct platform_device *pdev) ...@@ -830,6 +829,9 @@ static int caam_probe(struct platform_device *pdev)
return 0; return 0;
caam_remove: caam_remove:
#ifdef CONFIG_DEBUG_FS
debugfs_remove_recursive(ctrlpriv->dfs_root);
#endif
caam_remove(pdev); caam_remove(pdev);
return ret; return ret;
......
...@@ -67,6 +67,9 @@ struct caam_drv_private { ...@@ -67,6 +67,9 @@ struct caam_drv_private {
struct device *dev; struct device *dev;
struct platform_device **jrpdev; /* Alloc'ed array per sub-device */ struct platform_device **jrpdev; /* Alloc'ed array per sub-device */
#ifdef CONFIG_CAAM_QI
struct device *qidev;
#endif
struct platform_device *pdev; struct platform_device *pdev;
/* Physical-presence section */ /* Physical-presence section */
...@@ -110,9 +113,30 @@ struct caam_drv_private { ...@@ -110,9 +113,30 @@ struct caam_drv_private {
struct debugfs_blob_wrapper ctl_kek_wrap, ctl_tkek_wrap, ctl_tdsk_wrap; struct debugfs_blob_wrapper ctl_kek_wrap, ctl_tkek_wrap, ctl_tdsk_wrap;
struct dentry *ctl_kek, *ctl_tkek, *ctl_tdsk; struct dentry *ctl_kek, *ctl_tkek, *ctl_tdsk;
#ifdef CONFIG_CAAM_QI
struct dentry *qi_congested;
#endif
#endif #endif
}; };
void caam_jr_algapi_init(struct device *dev); void caam_jr_algapi_init(struct device *dev);
void caam_jr_algapi_remove(struct device *dev); void caam_jr_algapi_remove(struct device *dev);
#ifdef CONFIG_DEBUG_FS
static int caam_debugfs_u64_get(void *data, u64 *val)
{
*val = caam64_to_cpu(*(u64 *)data);
return 0;
}
static int caam_debugfs_u32_get(void *data, u64 *val)
{
*val = caam32_to_cpu(*(u32 *)data);
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(caam_fops_u32_ro, caam_debugfs_u32_get, NULL, "%llu\n");
DEFINE_SIMPLE_ATTRIBUTE(caam_fops_u64_ro, caam_debugfs_u64_get, NULL, "%llu\n");
#endif
#endif /* INTERN_H */ #endif /* INTERN_H */
This diff is collapsed.
/*
* Public definitions for the CAAM/QI (Queue Interface) backend.
*
* Copyright 2013-2016 Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
*/
#ifndef __QI_H__
#define __QI_H__
#include <soc/fsl/qman.h>
#include "compat.h"
#include "desc.h"
#include "desc_constr.h"
/*
* CAAM hardware constructs a job descriptor which points to a shared descriptor
* (as pointed by context_a of to-CAAM FQ).
* When the job descriptor is executed by DECO, the whole job descriptor
* together with shared descriptor gets loaded in DECO buffer, which is
* 64 words (each 32-bit) long.
*
* The job descriptor constructed by CAAM hardware has the following layout:
*
* HEADER (1 word)
* Shdesc ptr (1 or 2 words)
* SEQ_OUT_PTR (1 word)
* Out ptr (1 or 2 words)
* Out length (1 word)
* SEQ_IN_PTR (1 word)
* In ptr (1 or 2 words)
* In length (1 word)
*
* The shdesc ptr is used to fetch shared descriptor contents into DECO buffer.
*
* Apart from shdesc contents, the total number of words that get loaded in DECO
* buffer are '8' or '11'. The remaining words in DECO buffer can be used for
* storing shared descriptor.
*/
#define MAX_SDLEN ((CAAM_DESC_BYTES_MAX - DESC_JOB_IO_LEN) / CAAM_CMD_SZ)
extern bool caam_congested __read_mostly;
/*
* This is the request structure the driver application should fill while
* submitting a job to driver.
*/
struct caam_drv_req;
/*
* caam_qi_cbk - application's callback function invoked by the driver when the
* request has been successfully processed.
* @drv_req: original request that was submitted
* @status: completion status of request (0 - success, non-zero - error code)
*/
typedef void (*caam_qi_cbk)(struct caam_drv_req *drv_req, u32 status);
enum optype {
ENCRYPT,
DECRYPT,
GIVENCRYPT,
NUM_OP
};
/**
* caam_drv_ctx - CAAM/QI backend driver context
*
* The jobs are processed by the driver against a driver context.
* With every cryptographic context, a driver context is attached.
* The driver context contains data for private use by driver.
* For the applications, this is an opaque structure.
*
* @prehdr: preheader placed before shrd desc
* @sh_desc: shared descriptor
* @context_a: shared descriptor dma address
* @req_fq: to-CAAM request frame queue
* @rsp_fq: from-CAAM response frame queue
* @cpu: cpu on which to receive CAAM response
* @op_type: operation type
* @qidev: device pointer for CAAM/QI backend
*/
struct caam_drv_ctx {
u32 prehdr[2];
u32 sh_desc[MAX_SDLEN];
dma_addr_t context_a;
struct qman_fq *req_fq;
struct qman_fq *rsp_fq;
int cpu;
enum optype op_type;
struct device *qidev;
} ____cacheline_aligned;
/**
* caam_drv_req - The request structure the driver application should fill while
* submitting a job to driver.
* @fd_sgt: QMan S/G pointing to output (fd_sgt[0]) and input (fd_sgt[1])
* buffers.
* @cbk: callback function to invoke when job is completed
* @app_ctx: arbitrary context attached with request by the application
*
* The fields mentioned below should not be used by application.
* These are for private use by driver.
*
* @hdr__: linked list header to maintain list of outstanding requests to CAAM
* @hwaddr: DMA address for the S/G table.
*/
struct caam_drv_req {
struct qm_sg_entry fd_sgt[2];
struct caam_drv_ctx *drv_ctx;
caam_qi_cbk cbk;
void *app_ctx;
} ____cacheline_aligned;
/**
* caam_drv_ctx_init - Initialise a CAAM/QI driver context
*
* A CAAM/QI driver context must be attached with each cryptographic context.
* This function allocates memory for CAAM/QI context and returns a handle to
* the application. This handle must be submitted along with each enqueue
* request to the driver by the application.
*
* @cpu: CPU where the application prefers to the driver to receive CAAM
* responses. The request completion callback would be issued from this
* CPU.
* @sh_desc: shared descriptor pointer to be attached with CAAM/QI driver
* context.
*
* Returns a driver context on success or negative error code on failure.
*/
struct caam_drv_ctx *caam_drv_ctx_init(struct device *qidev, int *cpu,
u32 *sh_desc);
/**
* caam_qi_enqueue - Submit a request to QI backend driver.
*
* The request structure must be properly filled as described above.
*
* @qidev: device pointer for QI backend
* @req: CAAM QI request structure
*
* Returns 0 on success or negative error code on failure.
*/
int caam_qi_enqueue(struct device *qidev, struct caam_drv_req *req);
/**
* caam_drv_ctx_busy - Check if there are too many jobs pending with CAAM
* or too many CAAM responses are pending to be processed.
* @drv_ctx: driver context for which job is to be submitted
*
* Returns caam congestion status 'true/false'
*/
bool caam_drv_ctx_busy(struct caam_drv_ctx *drv_ctx);
/**
* caam_drv_ctx_update - Update QI driver context
*
* Invoked when shared descriptor is required to be change in driver context.
*
* @drv_ctx: driver context to be updated
* @sh_desc: new shared descriptor pointer to be updated in QI driver context
*
* Returns 0 on success or negative error code on failure.
*/
int caam_drv_ctx_update(struct caam_drv_ctx *drv_ctx, u32 *sh_desc);
/**
* caam_drv_ctx_rel - Release a QI driver context
* @drv_ctx: context to be released
*/
void caam_drv_ctx_rel(struct caam_drv_ctx *drv_ctx);
int caam_qi_init(struct platform_device *pdev);
int caam_qi_shutdown(struct device *dev);
/**
* qi_cache_alloc - Allocate buffers from CAAM-QI cache
*
* Invoked when a user of the CAAM-QI (i.e. caamalg-qi) needs data which has
* to be allocated on the hotpath. Instead of using malloc, one can use the
* services of the CAAM QI memory cache (backed by kmem_cache). The buffers
* will have a size of 256B, which is sufficient for hosting 16 SG entries.
*
* @flags: flags that would be used for the equivalent malloc(..) call
*
* Returns a pointer to a retrieved buffer on success or NULL on failure.
*/
void *qi_cache_alloc(gfp_t flags);
/**
* qi_cache_free - Frees buffers allocated from CAAM-QI cache
*
* Invoked when a user of the CAAM-QI (i.e. caamalg-qi) no longer needs
* the buffer previously allocated by a qi_cache_alloc call.
* No checking is being done, the call is a passthrough call to
* kmem_cache_free(...)
*
* @obj: object previously allocated using qi_cache_alloc()
*/
void qi_cache_free(void *obj);
#endif /* __QI_H__ */
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