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

Commit 1a6164c4 authored by Sahitya Tummala's avatar Sahitya Tummala Committed by Ram Prakash Gupta
Browse files

mmc: sdhci-msm-ice: Add Inline Crypto Engine (ICE) support



eMMC controller may have an Inline Crypto Engine (ICE) attached,
which can be used to encrypt/decrypt data going to/from eMMC.
This patch adds a new client driver sdhci-msm-ice.c which interacts
with ICE driver present in (drivers/crypto/msm/) and thus provides
an interface to the low-level SDHCI driver to do the data
encryption/decryption.

mmc: sdhci-msm: Add Inline Crypto Engine (ICE) support

Add ICE support to low-level driver sdhci-msm.c. This code is
primarily responsible for enabling ICE (if present),
managing ICE clocks, managing ICE suspend/resume and also provides
a few host->ops for sdhci driver to use ICE functionality.

mmc: sdhci: Add Inline Crypto Engine (ICE) support

This patch adds ICE support to sdhci driver. It uses the
new ICE host->ops like config/reset to configure/reset the
ICE HW as appropriate.

mmc: cqhci: Add Inline Crypto Engine (ICE) support

Add changes to configure ICE for data encryption/decryption
using CQE.

mmc: cqe: add new crypto_cfg_reset host operation

When encryption/decryption is enabled in CQ mode, the
legacy commands that are sent in HALT state will use
different slot other than slot 0 for crypto configuration
information. The slot that is selected depends on the last
slot that was used when it is in CQ mode.  This is causing
the data of legacy commands to be encrypted/decrypted based
on the wrong slot usage for crypto config details. Hence,
clear the crypto configuration of the slot used in CQ mode
whenever it gets completed.

mmc: sdhci-msm-ice: Add crypto register dump for debug upon error

Dump crypto related register information upon error for
debugging purpose.

crypto: ice: Make ICE init & reset API synchronous

ICE init & reset can be synchronous now because ICE does not need
to go to secure side for any ICE configuration. This would simplify
interface and make call more efficient.

crypto: ice: general driver clean-up

* Removed spinlock as it was not locking against anything
* Removed conversion of interrupt status to error number
  as it is not used by API client, and in case several bits are
  set only 1 error is ever handled and the rest get lost.
  Instead pass to the client the complete status.
* Removed redundant includes, variables
* vops structure is returned after performing a lookup in the DTS.
  There's no need for that as we already know the structure
  to return.
* Other minor corrections

mmc: sdhci-msm-ice: Update ice config vop to config_start

The config vop of the ice driver has been updated to config_start.
Updated the sdhci-ice driver to reflect this change.

mmc: sdhci-msm-ice: Enable ICE HCI if supported

Check if the SDHC has ICE HCI support. If support is present,
enable the cryptoghrapic support inside SDHC.

Also ensure that it is re-enabled after SDHC is reset.
By default ICE HCI is disabled.

mmc: sdhci-msm: Update ICE reset register offset for ICE HCI

SDHC v5.0 onwards the ICE reset register offset got updated.
Update the register offset based on the SDHC version.

mmc: sdhci-msm-ice: Factor out update config from sdhci_msm_ice_cfg

Factor out the logic of updating the SDHC ICE config registers
from sdhci_msm_ice_cfg().

For ICE3.0, different set of SDHC ICE registers are need to be updated.
So having this logic in separate functions, we can have logical
separation for ICE2.0 and ICE3.0.

mmc: sdhci-mmc-ice: Factor out ice_cfg_start from sdhci_msm_ice_cfg

Factor out the logic of getting ice config parameters from
sdhci_msm_ice_cfg().

With ICE2.0, same sdhci_msm_ice_cfg function is being called from cmdq
and noncq. But with ICE3.0 support, cmdq needs a separate host op.
Since this logic of getting ice config is common for noncq and cmdq,
by having it in separate function, same can be reused
in cmdq host op as-well.

mmc: sdhci-msm-ice: Add new sdhci host_op for updating ice config

Add new sdhci host_op for updating ice configuration while sending
request through cmdq. Adding provision for supporting the ice
context configuration for ICE HCI.

mmc: cmdq_hci: ice: Changes for supporting ICE HCI in CMDQ mode

On SDHC v5.0 onwards, SDHC includes the inline interface
for cryptographic operations which is ICE HCI.
This patch includes the driver changes for supporting crypto
operations with ICE HCI in cmdq mode.

Adding support for clearing ice configuration.
Once mmc request processing is completed, mmc driver has to
call config_end to ensure key information is cleared by ICE
driver. This call is optional for FDE but required for FBE.

mmc: sdhci-msm-ice: Changes for supporting ICE HCI in non CMDQ mode

SDHC v5.0 onwards, SDHC includes the inline interface for
cryptographic operations which is ICE HCI.

This patch includes the driver changes for supporting crypto
operations with ICE HCI in noncq mode.

mmc: host: sdhci: Add new host_op for clearing ice configuration

Add new host op for clearing ice configuration.
This config_end host op need to invoked for clearing ice configuration,
once mmc request processing is completed.

mmc: sdhci-msm-ice: add support for FBE over F2FS

Add support for FBE to work with F2FS filesystem on eMMC
based devices. For F2FS+FBE on eMMC, the cryto data unit
size (CDU size) should be 4KB as F2FS encrypts/decrypts
the data at min. 4KB blocks with (inode|pgidx) as it's
corresponding data unit number (DUN).

mmc: card: Set INLINECRYPT queue flag based on host capability

Set INLINECRYPT queue flag if the host can support h/w based inline
encryption.
This is needed to let the filesystem know that underlying storage
device can support inline encryption so that data encryption/
decryption would be handled at h/w level, not at filesystem.

Set inline-crypto support host flag if sdhc controller is capable
do performing inline encryption/decryption.

mmc: sdhci-msm: get the load notification from clock scaling

This is needed to scale up/down the ICE clock during runtime
as per the load on eMMC.

mmc: block: add req pointer to mmc request

This is needed by ICE (Inline Crypto Engine) driver to get
the ICE configuration data from the request.

Change-Id: Ie69c64f4dc0c31290dec50d905e8b3d436c86d62
Signed-off-by: default avatarVeerabhadrarao Badiganti <vbadigan@codeaurora.org>
Signed-off-by: default avatarSahitya Tummala <stummala@codeaurora.org>
Signed-off-by: default avatarVenkat Gopalakrishnan <venkatg@codeaurora.org>
Signed-off-by: default avatarRam Prakash Gupta <rampraka@codeaurora.org>
parent 1b30d1da
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -1595,6 +1595,7 @@ static int mmc_blk_cqe_issue_rw_rq(struct mmc_queue *mq, struct request *req)
	struct mmc_queue_req *mqrq = req_to_mmc_queue_req(req);

	mmc_blk_data_prep(mq, mqrq, 0, NULL, NULL);
	mqrq->brq.mrq.req = req;

	return mmc_blk_cqe_start_req(mq->card->host, &mqrq->brq.mrq);
}
@@ -2199,6 +2200,7 @@ static int mmc_blk_mq_issue_rw_rq(struct mmc_queue *mq,
	mmc_blk_rw_rq_prep(mqrq, mq->card, 0, mq);

	mqrq->brq.mrq.done = mmc_blk_mq_req_done;
	mqrq->brq.mrq.req = req;

	mmc_pre_req(host, &mqrq->brq.mrq);

+2 −0
Original line number Diff line number Diff line
@@ -369,6 +369,8 @@ static void mmc_setup_queue(struct mmc_queue *mq, struct mmc_card *card)
		min(host->max_blk_count, host->max_req_size / 512));
	blk_queue_max_segments(mq->queue, host->max_segs);
	blk_queue_max_segment_size(mq->queue, host->max_seg_size);
	if (host->inlinecrypt_support)
		queue_flag_set_unlocked(QUEUE_FLAG_INLINECRYPT, mq->queue);

	INIT_WORK(&mq->recovery_work, mmc_mq_recovery_handler);
	INIT_WORK(&mq->complete_work, mmc_blk_mq_complete_work);
+11 −0
Original line number Diff line number Diff line
@@ -149,6 +149,17 @@ config MMC_SDHCI_OF_AT91
	help
	  This selects the Atmel SDMMC driver

config MMC_SDHCI_MSM_ICE
	bool "Qualcomm Technologies, Inc Inline Crypto Engine for SDHCI core"
	depends on MMC_SDHCI_MSM && CRYPTO_DEV_QCOM_ICE
	help
	  This selects the QTI specific additions to support Inline Crypto
	  Engine (ICE). ICE accelerates the crypto operations and maintains
	  the high SDHCI performance.

	  Select this if you have ICE supported for SDHCI on QTI chipset.
	  If unsure, say N.

config MMC_SDHCI_OF_ESDHC
	tristate "SDHCI OF support for the Freescale eSDHC controller"
	depends on MMC_SDHCI_PLTFM
+1 −0
Original line number Diff line number Diff line
@@ -87,6 +87,7 @@ obj-$(CONFIG_MMC_SDHCI_OF_DWCMSHC) += sdhci-of-dwcmshc.o
obj-$(CONFIG_MMC_SDHCI_BCM_KONA)	+= sdhci-bcm-kona.o
obj-$(CONFIG_MMC_SDHCI_IPROC)		+= sdhci-iproc.o
obj-$(CONFIG_MMC_SDHCI_MSM)		+= sdhci-msm.o
obj-$(CONFIG_MMC_SDHCI_MSM_ICE)		+= sdhci-msm-ice.o
obj-$(CONFIG_MMC_SDHCI_ST)		+= sdhci-st.o
obj-$(CONFIG_MMC_SDHCI_MICROCHIP_PIC32)	+= sdhci-pic32.o
obj-$(CONFIG_MMC_SDHCI_BRCMSTB)		+= sdhci-brcmstb.o
+60 −1
Original line number Diff line number Diff line
@@ -241,6 +241,7 @@ static void __cqhci_enable(struct cqhci_host *cq_host)
{
	struct mmc_host *mmc = cq_host->mmc;
	u32 cqcfg;
	u32 cqcap = 0;

	cqcfg = cqhci_readl(cq_host, CQHCI_CFG);

@@ -258,6 +259,18 @@ static void __cqhci_enable(struct cqhci_host *cq_host)
	if (cq_host->caps & CQHCI_TASK_DESC_SZ_128)
		cqcfg |= CQHCI_TASK_DESC_SZ;

	cqcap = cqhci_readl(cq_host, CQHCI_CAP);
	if (cqcap & CQHCI_CAP_CS) {
		/*
		 * In case host controller supports cryptographic operations
		 * then, it uses 128bit task descriptor. Upper 64 bits of task
		 * descriptor would be used to pass crypto specific informaton.
		 */
		cq_host->caps |= CQHCI_CAP_CRYPTO_SUPPORT |
				CQHCI_TASK_DESC_SZ_128;
		cqcfg |= CQHCI_ICE_ENABLE;
	}

	cqhci_writel(cq_host, cqcfg, CQHCI_CFG);

	cqcfg |= CQHCI_ENABLE;
@@ -554,6 +567,30 @@ static inline int cqhci_tag(struct mmc_request *mrq)
	return mrq->cmd ? DCMD_SLOT : mrq->tag;
}

static inline
void cqe_prep_crypto_desc(struct cqhci_host *cq_host, u64 *task_desc,
			u64 ice_ctx)
{
	u64 *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 __force *)((u8 *)task_desc +
					CQHCI_TASK_DESC_TASK_PARAMS_SIZE);
		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;
@@ -562,6 +599,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));
@@ -585,9 +623,19 @@ static int cqhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
	}

	if (mrq->data) {
		if (cq_host->ops->crypto_cfg) {
			err = cq_host->ops->crypto_cfg(mmc, mrq, tag, &ice_ctx);
			if (err) {
				pr_err("%s: failed to configure crypto: err %d tag %d\n",
						mmc_hostname(mmc), err, 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);
		cqe_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",
@@ -619,7 +667,7 @@ static int cqhci_request(struct mmc_host *mmc, struct mmc_request *mrq)

	if (err)
		cqhci_post_req(mmc, mrq);

out:
	return err;
}

@@ -720,6 +768,7 @@ static void cqhci_finish_mrq(struct mmc_host *mmc, unsigned int tag)
	struct cqhci_slot *slot = &cq_host->slot[tag];
	struct mmc_request *mrq = slot->mrq;
	struct mmc_data *data;
	int err = 0;

	if (!mrq) {
		WARN_ONCE(1, "%s: cqhci: spurious TCN for tag %d\n",
@@ -739,12 +788,22 @@ static void cqhci_finish_mrq(struct mmc_host *mmc, unsigned int tag)

	data = mrq->data;
	if (data) {
		if (cq_host->ops->crypto_cfg_end) {
			err = cq_host->ops->crypto_cfg_end(mmc, mrq);
			if (err) {
				pr_err("%s: failed to end ice config: err %d tag %d\n",
						mmc_hostname(mmc), err, tag);
			}
		}
		if (data->error)
			data->bytes_xfered = 0;
		else
			data->bytes_xfered = data->blksz * data->blocks;
	}

	if (!(cq_host->caps & CQHCI_CAP_CRYPTO_SUPPORT) &&
			cq_host->ops->crypto_cfg_reset)
		cq_host->ops->crypto_cfg_reset(mmc, tag);
	mmc_cqe_request_done(mmc, mrq);
}

Loading