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.

Ported and fixed the merged conflicts in cqhci.c file
Added new member in cqhci_host to get platform device from sdhci
during cqhci_pltfm_init().

(cherry picked from mainline kernel_msm-4.19 commit 2543833e).
Conflicts:
	drivers/mmc/host/cqhci.c

Test:
1. Device booted upto UI with File Based Encryption enabled.
2. Key insertion using fscryptctl tool.
3. Created new files under /data and checked retention across
   multiple re-boots.
4. vts_kernel_encryption_test tests.
5. check_encryption test for verifying metadata encryption.

Change-Id: I6860cd29d6f044f559385d438048b850faf9a8be
Signed-off-by: Neeraj Soni <neersoni@codeaurora.org>
Signed-off-by: Vaibhav Agrawal <vagrawa@codeaurora.org>
This commit is contained in:
Neeraj Soni 2020-01-29 16:16:18 +05:30 • committed by Gerrit - the friendly Code Review server
commit cd86102b66
2 changed files with 101 additions and 1 deletions

View file

@ -18,6 +18,7 @@
#include <linux/mmc/card.h>
#include "cqhci.h"
#include "cqhci-crypto.h"
#define DCMD_SLOT 31
#define NUM_SLOTS 32
@ -138,6 +139,8 @@ static void cqhci_dumpregs(struct cqhci_host *cq_host)
cqhci_readl(cq_host, CQHCI_CRI),
cqhci_readl(cq_host, CQHCI_CRA));
cqhci_crypto_debug(cq_host);
if (cq_host->ops->dumpregs)
cq_host->ops->dumpregs(mmc);
else
@ -258,6 +261,11 @@ static void __cqhci_enable(struct cqhci_host *cq_host)
if (cq_host->caps & CQHCI_TASK_DESC_SZ_128)
cqcfg |= CQHCI_TASK_DESC_SZ;
if (cqhci_host_is_crypto_supported(cq_host)) {
cqhci_crypto_enable(cq_host);
cqcfg |= CQHCI_ICE_ENABLE;
}
cqhci_writel(cq_host, cqcfg, CQHCI_CFG);
cqhci_writel(cq_host, lower_32_bits(cq_host->desc_dma_base),
@ -290,6 +298,9 @@ static void __cqhci_disable(struct cqhci_host *cq_host)
{
u32 cqcfg;
if (cqhci_host_is_crypto_supported(cq_host))
cqhci_crypto_disable(cq_host);
cqcfg = cqhci_readl(cq_host, CQHCI_CFG);
cqcfg &= ~CQHCI_ENABLE;
cqhci_writel(cq_host, cqcfg, CQHCI_CFG);
@ -303,6 +314,8 @@ int cqhci_deactivate(struct mmc_host *mmc)
{
struct cqhci_host *cq_host = mmc->cqe_private;
cqhci_crypto_suspend(cq_host);
if (cq_host->enabled && cq_host->activated)
__cqhci_disable(cq_host);
@ -561,6 +574,30 @@ static inline int cqhci_tag(struct mmc_request *mrq)
return mrq->cmd ? DCMD_SLOT : mrq->tag;
}
static inline
void cqhci_prep_crypto_desc(struct cqhci_host *cq_host, u64 *task_desc,
u64 ice_ctx)
{
__le64 *ice_desc = NULL;
if (cq_host->caps & CQHCI_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 = (__le64 *)((u8 *)task_desc +
CQHCI_TASK_DESC_ICE_PARAM_OFFSET);
memset(ice_desc, 0, CQHCI_TASK_DESC_ICE_PARAMS_SIZE);
/*
* Assign upper 64bits data of task descritor with ice context
*/
if (ice_ctx)
*ice_desc = cpu_to_le64(ice_ctx);
}
}
static int cqhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
{
int err = 0;
@ -569,6 +606,7 @@ static int cqhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
int tag = cqhci_tag(mrq);
struct cqhci_host *cq_host = mmc->cqe_private;
unsigned long flags;
u64 ice_ctx = 0;
if (!cq_host->enabled) {
pr_err("%s: cqhci: not enabled\n", mmc_hostname(mmc));
@ -592,9 +630,17 @@ static int cqhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
}
if (mrq->data) {
err = cqhci_crypto_get_ctx(cq_host, mrq, &ice_ctx);
if (err) {
pr_err("%s: failed to retrieve crypto ctx for tag %d\n",
mmc_hostname(mmc), tag);
goto out;
}
task_desc = (__le64 __force *)get_desc(cq_host, tag);
cqhci_prep_task_desc(mrq, &data, 1);
*task_desc = cpu_to_le64(data);
cqhci_prep_crypto_desc(cq_host, task_desc, ice_ctx);
err = cqhci_prep_tran_desc(mrq, cq_host, tag);
if (err) {
pr_err("%s: cqhci: failed to setup tx desc: %d\n",
@ -628,6 +674,9 @@ out_unlock:
if (err)
cqhci_post_req(mmc, mrq);
if (mrq->data)
cqhci_complete_crypto_desc(cq_host, mrq, NULL);
out:
return err;
}
@ -635,7 +684,15 @@ out_unlock:
static void cqhci_crypto_update_queue(struct mmc_host *mmc,
struct request_queue *queue)
{
//struct cqhci_host *cq_host = mmc->cqe_private;
struct cqhci_host *cq_host = mmc->cqe_private;
if (cq_host->caps & CQHCI_CAP_CRYPTO_SUPPORT) {
if (queue)
cqhci_crypto_setup_rq_keyslot_manager(cq_host, queue);
else
pr_err("%s can not register keyslot manager\n",
mmc_hostname(mmc));
}
}
#endif
@ -755,6 +812,8 @@ static void cqhci_finish_mrq(struct mmc_host *mmc, unsigned int tag)
data = mrq->data;
if (data) {
cqhci_complete_crypto_desc(cq_host, mrq, NULL);
if (data->error)
data->bytes_xfered = 0;
else
@ -942,6 +1001,8 @@ static void cqhci_recovery_start(struct mmc_host *mmc)
pr_debug("%s: cqhci: %s\n", mmc_hostname(mmc), __func__);
cqhci_crypto_reset(cq_host);
WARN_ON(!cq_host->recovery_halt);
cqhci_halt(mmc, CQHCI_START_HALT_TIMEOUT);
@ -1062,6 +1123,8 @@ static void cqhci_recovery_finish(struct mmc_host *mmc)
cqhci_set_irqs(cq_host, CQHCI_IS_MASK);
cqhci_crypto_recovery_finish(cq_host);
pr_debug("%s: cqhci: recovery done\n", mmc_hostname(mmc));
}
@ -1103,6 +1166,11 @@ struct cqhci_host *cqhci_pltfm_init(struct platform_device *pdev)
dev_err(&pdev->dev, "failed to remap cqhci regs\n");
return ERR_PTR(-EBUSY);
}
#ifdef CONFIG_MMC_CQHCI_CRYPTO_QTI
cq_host->pdev = pdev;
#endif /* CONFIG_MMC_CQHCI_CRYPTO_QTI */
dev_dbg(&pdev->dev, "CMDQ ioremap: done\n");
return cq_host;
@ -1148,6 +1216,13 @@ int cqhci_init(struct cqhci_host *cq_host, struct mmc_host *mmc,
spin_lock_init(&cq_host->lock);
err = cqhci_host_init_crypto(cq_host);
if (err) {
pr_err("%s: CQHCI version %u.%02u Crypto init failed err %d\n",
mmc_hostname(mmc), cqhci_ver_major(cq_host),
cqhci_ver_minor(cq_host), err);
}
init_completion(&cq_host->halt_comp);
init_waitqueue_head(&cq_host->wait_queue);

View file

@ -32,6 +32,7 @@
#define CQHCI_DCMD 0x00001000
#define CQHCI_TASK_DESC_SZ 0x00000100
#define CQHCI_ENABLE 0x00000001
#define CQHCI_ICE_ENABLE 0x00000002
/* control */
#define CQHCI_CTL 0x0C
@ -148,11 +149,20 @@
#define CQHCI_DAT_LENGTH(x) (((x) & 0xFFFF) << 16)
#define CQHCI_DAT_ADDR_LO(x) (((x) & 0xFFFFFFFF) << 32)
#define CQHCI_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 CQHCI_TASK_DESC_ICE_PARAM_OFFSET 8
/* ICE descriptor size */
#define CQHCI_TASK_DESC_ICE_PARAMS_SIZE 8
struct cqhci_host_ops;
struct mmc_host;
struct mmc_request;
struct cqhci_slot;
struct cqhci_host;
/* CCAP - Crypto Capability 100h */
union cqhci_crypto_capabilities {
@ -240,6 +250,7 @@ struct cqhci_host_crypto_variant_ops {
struct cqhci_host {
const struct cqhci_host_ops *ops;
void __iomem *mmio;
void __iomem *icemmio;
struct mmc_host *mmc;
spinlock_t lock;
@ -255,6 +266,7 @@ struct cqhci_host {
u32 dcmd_slot;
u32 caps;
#define CQHCI_TASK_DESC_SZ_128 0x1
#define CQHCI_CAP_CRYPTO_SUPPORT 0x2
u32 quirks;
#define CQHCI_QUIRK_SHORT_TXFR_DESC_SZ 0x1
@ -291,6 +303,19 @@ struct cqhci_host {
struct completion halt_comp;
wait_queue_head_t wait_queue;
struct cqhci_slot *slot;
const struct cqhci_host_crypto_variant_ops *crypto_vops;
#ifdef CONFIG_MMC_CQHCI_CRYPTO
union cqhci_crypto_capabilities crypto_capabilities;
union cqhci_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_MMC_CQHCI_CRYPTO */
#ifdef CONFIG_MMC_CQHCI_CRYPTO_QTI
struct platform_device *pdev;
#endif /* CONFIG_MMC_CQHCI_CRYPTO_QTI */
};
struct cqhci_host_ops {