Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cd86102b authored by Neeraj Soni's avatar Neeraj Soni Committed by Gerrit - the friendly Code Review server
Browse files

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: default avatarNeeraj Soni <neersoni@codeaurora.org>
Signed-off-by: default avatarVaibhav Agrawal <vagrawa@codeaurora.org>
parent bec27fe2
Loading
Loading
Loading
Loading
+76 −1
Original line number Diff line number Diff line
@@ -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 @@ static int cqhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
	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 @@ static int cqhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
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);

+25 −0
Original line number Diff line number Diff line
@@ -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 {