mmc: cqhci: Add inline crypto support to cqhci

Wire up cqhci.c with the eMMC Crypto API and support for block layer
inline encryption additions and the keyslot manager.

Change-Id: I0fb63a3d7601a8979386ecf1c65bc5c44369429e
Signed-off-by: Neeraj Soni <neersoni@codeaurora.org>
tirimbino
Neeraj Soni 5 years ago committed by Gerrit - the friendly Code Review server
parent 68c229bbb1
commit 5a7d7052d9
  1. 68
      drivers/mmc/host/cmdq_hci.c
  2. 20
      drivers/mmc/host/cmdq_hci.h

@ -29,8 +29,10 @@
#include <linux/random.h>
#include "cmdq_hci.h"
#include "cmdq_hci-crypto.h"
#include "sdhci.h"
#include "sdhci-msm.h"
#include "../core/queue.h"
#define DCMD_SLOT 31
#define NUM_SLOTS 32
@ -277,6 +279,8 @@ static void cmdq_dumpregs(struct cmdq_host *cq_host)
cmdq_readl(cq_host, CQ_VENDOR_CFG + offset));
pr_err(DRV_NAME ": ===========================================\n");
cmdq_crypto_debug(cq_host);
cmdq_dump_task_history(cq_host);
if (cq_host->ops->dump_vendor_regs)
cq_host->ops->dump_vendor_regs(mmc);
@ -404,6 +408,11 @@ static int cmdq_enable(struct mmc_host *mmc)
cqcfg = ((cq_host->caps & CMDQ_TASK_DESC_SZ_128 ? CQ_TASK_DESC_SZ : 0) |
(dcmd_enable ? CQ_DCMD : 0));
if (cmdq_host_is_crypto_supported(cq_host)) {
cmdq_crypto_enable(cq_host);
cqcfg |= CQ_ICE_ENABLE;
}
cmdq_writel(cq_host, cqcfg, CQCFG);
/* enable CQ_HOST */
cmdq_writel(cq_host, cmdq_readl(cq_host, CQCFG) | CQ_ENABLE,
@ -473,6 +482,9 @@ static void cmdq_disable_nosync(struct mmc_host *mmc, bool soft)
{
struct cmdq_host *cq_host = (struct cmdq_host *)mmc_cmdq_private(mmc);
if (cmdq_host_is_crypto_supported(cq_host))
cmdq_crypto_disable(cq_host);
if (soft) {
cmdq_writel(cq_host, cmdq_readl(
cq_host, CQCFG) & ~(CQ_ENABLE),
@ -512,6 +524,8 @@ static void cmdq_reset(struct mmc_host *mmc, bool soft)
cmdq_disable(mmc, true);
cmdq_crypto_reset(cq_host);
if (cq_host->ops->reset) {
ret = cq_host->ops->reset(mmc);
if (ret) {
@ -541,6 +555,29 @@ static void cmdq_reset(struct mmc_host *mmc, bool soft)
mmc_host_clr_cq_disable(mmc);
}
static inline void cmdq_prep_crypto_desc(struct cmdq_host *cq_host,
u64 *task_desc, u64 ice_ctx)
{
u64 *ice_desc = NULL;
if (cq_host->caps & CMDQ_CAP_CRYPTO_SUPPORT) {
/*
* Get the address of ice context for the given task descriptor.
* ice context is present in the upper 64bits of task descriptor
* ice_conext_base_address = task_desc + 8-bytes
*/
ice_desc = (u64 *)((u8 *)task_desc +
CQ_TASK_DESC_ICE_PARAM_OFFSET);
memset(ice_desc, 0, CQ_TASK_DESC_ICE_PARAMS_SIZE);
/*
* Assign upper 64bits data of task descritor with ice context
*/
if (ice_ctx)
*ice_desc = ice_ctx;
}
}
static void cmdq_prep_task_desc(struct mmc_request *mrq,
u64 *data, bool intr, bool qbr)
{
@ -742,6 +779,7 @@ static int cmdq_request(struct mmc_host *mmc, struct mmc_request *mrq)
u32 tag = mrq->cmdq_req->tag;
struct cmdq_host *cq_host = (struct cmdq_host *)mmc_cmdq_private(mmc);
struct sdhci_host *host = mmc_priv(mmc);
u64 ice_ctx = 0;
if (!cq_host->enabled) {
pr_err("%s: CMDQ host not enabled yet !!!\n",
@ -760,12 +798,22 @@ static int cmdq_request(struct mmc_host *mmc, struct mmc_request *mrq)
goto ring_doorbell;
}
err = cmdq_crypto_get_ctx(cq_host, mrq, &ice_ctx);
if (err) {
mmc->err_stats[MMC_ERR_ICE_CFG]++;
pr_err("%s: failed to retrieve crypto ctx for tag %d\n",
mmc_hostname(mmc), tag);
goto ice_err;
}
task_desc = (__le64 __force *)get_desc(cq_host, tag);
cmdq_prep_task_desc(mrq, &data, 1,
(mrq->cmdq_req->cmdq_req_flags & QBR));
*task_desc = cpu_to_le64(data);
cmdq_prep_crypto_desc(cq_host, task_desc, ice_ctx);
cmdq_log_task_desc_history(cq_host, *task_desc, false);
err = cmdq_prep_tran_desc(mrq, cq_host, tag);
@ -792,8 +840,12 @@ ring_doorbell:
/* Commit the doorbell write immediately */
wmb();
return err;
ice_err:
if (err)
cmdq_runtime_pm_put(cq_host);
out:
return err;
}
@ -810,6 +862,8 @@ static void cmdq_finish_data(struct mmc_host *mmc, unsigned int tag)
if (tag == cq_host->dcmd_slot)
mrq->cmd->resp[0] = cmdq_readl(cq_host, CQCRDCT);
cmdq_complete_crypto_desc(cq_host, mrq, NULL);
if (mrq->cmdq_req->cmdq_req_flags & DCMD)
cmdq_writel(cq_host,
cmdq_readl(cq_host, CQ_VENDOR_CFG + offset) |
@ -1280,7 +1334,15 @@ static int cmdq_late_init(struct mmc_host *mmc)
static void cqhci_crypto_update_queue(struct mmc_host *mmc,
struct request_queue *queue)
{
//struct cqhci_host *cq_host = mmc->cqe_private;
struct cmdq_host *cq_host = (struct cmdq_host *)mmc_cmdq_private(mmc);
if (cq_host->caps & CMDQ_CAP_CRYPTO_SUPPORT) {
if (queue)
cmdq_crypto_setup_rq_keyslot_manager(cq_host, queue);
else
pr_err("%s can not register keyslot manager\n",
__func__);
}
}
static const struct mmc_cmdq_host_ops cmdq_host_ops = {
@ -1347,6 +1409,10 @@ int cmdq_init(struct cmdq_host *cq_host, struct mmc_host *mmc,
if (!cq_host->mrq_slot)
return -ENOMEM;
err = cmdq_host_init_crypto(cq_host);
if (err)
pr_err("%s: CMDQ Crypto init failed err %d\n", err);
init_completion(&cq_host->halt_comp);
return err;
}

@ -28,6 +28,7 @@
#define CQ_DCMD 0x00001000
#define CQ_TASK_DESC_SZ 0x00000100
#define CQ_ENABLE 0x00000001
#define CQ_ICE_ENABLE 0x00000002
/* control */
#define CQCTL 0x0C
@ -147,6 +148,14 @@
#define DAT_LENGTH(x) ((x & 0xFFFF) << 16)
#define DAT_ADDR_LO(x) ((x & 0xFFFFFFFF) << 32)
#define DAT_ADDR_HI(x) ((x & 0xFFFFFFFF) << 0)
#define DATA_UNIT_NUM(x) (((u64)(x) & 0xFFFFFFFF) << 0)
#define CRYPTO_CONFIG_INDEX(x) (((u64)(x) & 0xFF) << 32)
#define CRYPTO_ENABLE(x) (((u64)(x) & 0x1) << 47)
/* ICE context is present in the upper 64bits of task descriptor */
#define CQ_TASK_DESC_ICE_PARAM_OFFSET 8
/* ICE descriptor size */
#define CQ_TASK_DESC_ICE_PARAMS_SIZE 8
/*
* Add new macro for updated CQ vendor specific
@ -247,6 +256,7 @@ struct task_history {
struct cmdq_host {
const struct cmdq_host_ops *ops;
void __iomem *mmio;
void __iomem *icemmio;
struct mmc_host *mmc;
/* 64 bit DMA */
@ -256,6 +266,7 @@ struct cmdq_host {
u32 dcmd_slot;
u32 caps;
#define CMDQ_TASK_DESC_SZ_128 0x1
#define CMDQ_CAP_CRYPTO_SUPPORT 0x2
u32 quirks;
#define CMDQ_QUIRK_SHORT_TXFR_DESC_SZ 0x1
@ -290,6 +301,15 @@ struct cmdq_host {
struct completion halt_comp;
struct mmc_request **mrq_slot;
void *private;
const struct cmdq_host_crypto_variant_ops *crypto_vops;
#ifdef CONFIG_MMC_CQ_HCI_CRYPTO
union cmdq_crypto_capabilities crypto_capabilities;
union cmdq_crypto_cap_entry *crypto_cap_array;
u32 crypto_cfg_register;
#ifdef CONFIG_BLK_INLINE_ENCRYPTION
struct keyslot_manager *ksm;
#endif /* CONFIG_BLK_INLINE_ENCRYPTION */
#endif /* CONFIG_SCSI_CQHCI_CRYPTO */
};
struct cmdq_host_ops {

Loading…
Cancel
Save