Loading drivers/mmc/host/cmdq_hci.c +130 −4 Original line number Diff line number Diff line Loading @@ -145,6 +145,29 @@ static void cmdq_clear_set_irqs(struct cmdq_host *cq_host, u32 clear, u32 set) mb(); } static int cmdq_clear_task_poll(struct cmdq_host *cq_host, unsigned int tag) { int retries = 100; cmdq_clear_set_irqs(cq_host, CQIS_TCL, 0); cmdq_writel(cq_host, 1<<tag, CQTCLR); while (retries) { /* * Task Clear register and doorbell, * both should indicate that task is cleared */ if ((cmdq_readl(cq_host, CQTCLR) & 1<<tag) || (cmdq_readl(cq_host, CQTDBR) & 1<<tag)) { udelay(5); retries--; continue; } else break; } cmdq_clear_set_irqs(cq_host, 0, CQIS_TCL); return retries ? 0 : -ETIMEDOUT; } #define DRV_NAME "cmdq-host" Loading Loading @@ -345,6 +368,7 @@ static int cmdq_enable(struct mmc_host *mmc) { int err = 0; u32 cqcfg; u32 cqcap = 0; bool dcmd_enable; struct cmdq_host *cq_host = mmc_cmdq_private(mmc); Loading Loading @@ -373,6 +397,18 @@ 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)); cqcap = cmdq_readl(cq_host, CQCAP); if (cqcap & CQCAP_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 |= CMDQ_CAP_CRYPTO_SUPPORT | CMDQ_TASK_DESC_SZ_128; cqcfg |= CQ_ICE_ENABLE; } cmdq_writel(cq_host, cqcfg, CQCFG); /* enable CQ_HOST */ cmdq_writel(cq_host, cmdq_readl(cq_host, CQCFG) | CQ_ENABLE, Loading Loading @@ -688,6 +724,30 @@ static void cmdq_prep_dcmd_desc(struct mmc_host *mmc, upper_32_bits(*task_desc)); } 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 = (__le64 *)((u8 *)task_desc + CQ_TASK_DESC_TASK_PARAMS_SIZE); 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 = cpu_to_le64(ice_ctx); } } static void cmdq_pm_qos_vote(struct sdhci_host *host, struct mmc_request *mrq) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); Loading @@ -711,6 +771,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", Loading @@ -730,7 +791,7 @@ static int cmdq_request(struct mmc_host *mmc, struct mmc_request *mrq) } if (cq_host->ops->crypto_cfg) { err = cq_host->ops->crypto_cfg(mmc, mrq, tag); 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); Loading @@ -743,6 +804,9 @@ static int cmdq_request(struct mmc_host *mmc, struct mmc_request *mrq) 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); Loading Loading @@ -787,7 +851,8 @@ static void cmdq_finish_data(struct mmc_host *mmc, unsigned int tag) CMDQ_SEND_STATUS_TRIGGER, CQ_VENDOR_CFG); cmdq_runtime_pm_put(cq_host); if (cq_host->ops->crypto_cfg_reset) if (!(cq_host->caps & CMDQ_CAP_CRYPTO_SUPPORT) && cq_host->ops->crypto_cfg_reset) cq_host->ops->crypto_cfg_reset(mmc, tag); mrq->done(mrq); } Loading @@ -801,6 +866,8 @@ irqreturn_t cmdq_irq(struct mmc_host *mmc, int err) struct mmc_request *mrq; int ret; u32 dbr_set = 0; u32 dev_pend_set = 0; int stat_err = 0; status = cmdq_readl(cq_host, CQIS); Loading @@ -809,7 +876,9 @@ irqreturn_t cmdq_irq(struct mmc_host *mmc, int err) MMC_TRACE(mmc, "%s: CQIS: 0x%x err: %d\n", __func__, status, err); if (err || (status & CQIS_RED)) { stat_err = status & (CQIS_RED | CQIS_GCE | CQIS_ICCE); if (err || stat_err) { err_info = cmdq_readl(cq_host, CQTERRI); pr_err("%s: err: %d status: 0x%08x task-err-info (0x%08lx)\n", mmc_hostname(mmc), err, status, err_info); Loading Loading @@ -912,7 +981,7 @@ irqreturn_t cmdq_irq(struct mmc_host *mmc, int err) * CQE detected a response error from device * In most cases, this would require a reset. */ if (status & CQIS_RED) { if (stat_err & CQIS_RED) { /* * will check if the RED error is due to a bkops * exception once the queue is empty Loading @@ -931,6 +1000,62 @@ irqreturn_t cmdq_irq(struct mmc_host *mmc, int err) mrq->cmdq_req->resp_arg = cmdq_readl(cq_host, CQCRA); } /* * Generic Crypto error detected by CQE. * Its a fatal, would require cmdq reset. */ if (stat_err & CQIS_GCE) { if (mrq->data) mrq->data->error = -EIO; pr_err("%s: Crypto generic error while processing task %lu!", mmc_hostname(mmc), tag); MMC_TRACE(mmc, "%s: GCE error detected with tag %lu\n", __func__, tag); } /* * Invalid crypto config error detected by CQE, clear the task. * Task can be cleared only when CQE is halt state. */ if (stat_err & CQIS_ICCE) { /* * Invalid Crypto Config Error is detected at the * beginning of the transfer before the actual execution * started. So just clear the task in CQE. No need to * clear in device. Only the task which caused ICCE has * to be cleared. Other tasks can be continue processing * The first task which is about to be prepared would * cause ICCE Error. */ dbr_set = cmdq_readl(cq_host, CQTDBR); dev_pend_set = cmdq_readl(cq_host, CQDPT); if (dbr_set ^ dev_pend_set) tag = ffs(dbr_set ^ dev_pend_set) - 1; mrq = get_req_by_tag(cq_host, tag); pr_err("%s: Crypto config error while processing task %lu!", mmc_hostname(mmc), tag); MMC_TRACE(mmc, "%s: ICCE error with tag %lu\n", __func__, tag); if (mrq->data) mrq->data->error = -EIO; else if (mrq->cmd) mrq->cmd->error = -EIO; /* * If CQE is halted and tag is valid then clear the task * then un-halt CQE and set flag to skip error recovery. * If any of the condtions is not met thene it will * enter into default error recovery path. */ if (!ret && (dbr_set ^ dev_pend_set)) { ret = cmdq_clear_task_poll(cq_host, tag); if (ret) { pr_err("%s: %s: task[%lu] clear failed ret=%d\n", mmc_hostname(mmc), __func__, tag, ret); } else if (!cmdq_halt_poll(mmc, false)) { mrq->cmdq_req->skip_err_handling = true; } } } cmdq_finish_data(mmc, tag); } else { cmdq_writel(cq_host, status, CQIS); Loading Loading @@ -1001,6 +1126,7 @@ static int cmdq_halt_poll(struct mmc_host *mmc, bool halt) cq_host->ops->clear_set_irqs(mmc, true); cmdq_writel(cq_host, cmdq_readl(cq_host, CQCTL) & ~HALT, CQCTL); mmc_host_clr_halt(mmc); return 0; } Loading drivers/mmc/host/cmdq_hci.h +10 −2 Original line number Diff line number Diff line Loading @@ -18,11 +18,13 @@ #define CQVER 0x00 /* capabilities */ #define CQCAP 0x04 #define CQCAP_CS (1 << 28) /* configuration */ #define CQCFG 0x08 #define CQ_DCMD 0x00001000 #define CQ_TASK_DESC_SZ 0x00000100 #define CQ_ENABLE 0x00000001 #define CQ_ICE_ENABLE 0x00000002 /* control */ #define CQCTL 0x0C Loading @@ -35,6 +37,8 @@ #define CQIS_TCC (1 << 1) #define CQIS_RED (1 << 2) #define CQIS_TCL (1 << 3) #define CQIS_GCE (1 << 4) #define CQIS_ICCE (1 << 5) /* interrupt status enable */ #define CQISTE 0x14 Loading Loading @@ -110,7 +114,7 @@ /* command response argument */ #define CQCRA 0x5C #define CQ_INT_ALL 0xF #define CQ_INT_ALL 0x3F #define CQIC_DEFAULT_ICCTH 31 #define CQIC_DEFAULT_ICTOVAL 1 Loading Loading @@ -144,6 +148,9 @@ #define CQ_VENDOR_CFG 0x100 #define CMDQ_SEND_STATUS_TRIGGER (1 << 31) #define CQ_TASK_DESC_TASK_PARAMS_SIZE 8 #define CQ_TASK_DESC_ICE_PARAMS_SIZE 8 struct task_history { u64 task; bool is_dcmd; Loading @@ -161,6 +168,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 Loading Loading @@ -209,7 +217,7 @@ struct cmdq_host_ops { int (*reset)(struct mmc_host *mmc); void (*post_cqe_halt)(struct mmc_host *mmc); int (*crypto_cfg)(struct mmc_host *mmc, struct mmc_request *mrq, u32 slot); u32 slot, u64 *ice_ctx); void (*crypto_cfg_reset)(struct mmc_host *mmc, unsigned int slot); }; Loading drivers/mmc/host/sdhci-msm-ice.c +68 −2 Original line number Diff line number Diff line Loading @@ -276,6 +276,58 @@ void sdhci_msm_ice_update_cfg(struct sdhci_host *host, u64 lba, mb(); } static inline void sdhci_msm_ice_hci_update_cmdq_cfg(u64 dun, unsigned int bypass, short key_index, u64 *ice_ctx) { /* * The naming convention got changed between ICE2.0 and ICE3.0 * registers fields. Below is the equivalent names for * ICE3.0 Vs ICE2.0: * Data Unit Number(DUN) == Logical Base address(LBA) * Crypto Configuration index (CCI) == Key Index * Crypto Enable (CE) == !BYPASS */ if (ice_ctx) *ice_ctx = DATA_UNIT_NUM(dun) | CRYPTO_CONFIG_INDEX(key_index) | CRYPTO_ENABLE(!bypass); } static void sdhci_msm_ice_hci_update_noncq_cfg(struct sdhci_host *host, u64 dun, unsigned int bypass, short key_index) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct sdhci_msm_host *msm_host = pltfm_host->priv; unsigned int crypto_params = 0; /* * The naming convention got changed between ICE2.0 and ICE3.0 * registers fields. Below is the equivalent names for * ICE3.0 Vs ICE2.0: * Data Unit Number(DUN) == Logical Base address(LBA) * Crypto Configuration index (CCI) == Key Index * Crypto Enable (CE) == !BYPASS */ /* Configure ICE bypass mode */ crypto_params |= (!bypass & MASK_SDHCI_MSM_ICE_HCI_PARAM_CE) << OFFSET_SDHCI_MSM_ICE_HCI_PARAM_CE; /* Configure Crypto Configure Index (CCI) */ crypto_params |= (key_index & MASK_SDHCI_MSM_ICE_HCI_PARAM_CCI) << OFFSET_SDHCI_MSM_ICE_HCI_PARAM_CCI; writel_relaxed((crypto_params & 0xFFFFFFFF), msm_host->cryptoio + ICE_NONCQ_CRYPTO_PARAMS); /* Update DUN */ writel_relaxed((dun & 0xFFFFFFFF), msm_host->cryptoio + ICE_NONCQ_CRYPTO_DUN); /* Ensure ICE registers are configured before issuing SDHCI request */ mb(); } int sdhci_msm_ice_cfg(struct sdhci_host *host, struct mmc_request *mrq, u32 slot) { Loading Loading @@ -308,7 +360,14 @@ int sdhci_msm_ice_cfg(struct sdhci_host *host, struct mmc_request *mrq, slot, bypass, key_index); } if (msm_host->ice_hci_support) { /* For ICE HCI / ICE3.0 */ sdhci_msm_ice_hci_update_noncq_cfg(host, lba, bypass, key_index); } else { /* For ICE versions earlier to ICE3.0 */ sdhci_msm_ice_update_cfg(host, lba, slot, bypass, key_index); } return 0; } Loading Loading @@ -344,7 +403,14 @@ int sdhci_msm_ice_cmdq_cfg(struct sdhci_host *host, slot, bypass, key_index); } if (msm_host->ice_hci_support) { /* For ICE HCI / ICE3.0 */ sdhci_msm_ice_hci_update_cmdq_cfg(lba, bypass, key_index, ice_ctx); } else { /* For ICE versions earlier to ICE3.0 */ sdhci_msm_ice_update_cfg(host, lba, slot, bypass, key_index); } return 0; } Loading drivers/mmc/host/sdhci-msm-ice.h +8 −2 Original line number Diff line number Diff line Loading @@ -42,6 +42,8 @@ #define ICE_HCI_SUPPORT (1 << 28) #define ICE_CQ_CONFIG 0x08 #define CRYPTO_GENERAL_ENABLE (1 << 1) #define ICE_NONCQ_CRYPTO_PARAMS 0x70 #define ICE_NONCQ_CRYPTO_DUN 0x74 /* ICE3.0 register which got added hc reg space */ #define HC_VENDOR_SPECIFIC_FUNC4 0x260 Loading @@ -52,8 +54,10 @@ /* SDHCI MSM ICE CTRL Info register offset */ enum { OFFSET_SDHCI_MSM_ICE_CTRL_INFO_BYPASS = 0, OFFSET_SDHCI_MSM_ICE_CTRL_INFO_KEY_INDEX = 0x1, OFFSET_SDHCI_MSM_ICE_CTRL_INFO_CDU = 0x6, OFFSET_SDHCI_MSM_ICE_CTRL_INFO_KEY_INDEX = 1, OFFSET_SDHCI_MSM_ICE_CTRL_INFO_CDU = 6, OFFSET_SDHCI_MSM_ICE_HCI_PARAM_CCI = 0, OFFSET_SDHCI_MSM_ICE_HCI_PARAM_CE = 8, }; /* SDHCI MSM ICE CTRL Info register masks */ Loading @@ -61,6 +65,8 @@ enum { MASK_SDHCI_MSM_ICE_CTRL_INFO_BYPASS = 0x1, MASK_SDHCI_MSM_ICE_CTRL_INFO_KEY_INDEX = 0x1F, MASK_SDHCI_MSM_ICE_CTRL_INFO_CDU = 0x7, MASK_SDHCI_MSM_ICE_HCI_PARAM_CE = 0x1, MASK_SDHCI_MSM_ICE_HCI_PARAM_CCI = 0xff }; /* SDHCI MSM ICE encryption/decryption bypass state */ Loading drivers/mmc/host/sdhci.c +4 −3 Original line number Diff line number Diff line Loading @@ -3775,7 +3775,7 @@ static void sdhci_cmdq_post_cqe_halt(struct mmc_host *mmc) sdhci_writel(host, SDHCI_INT_RESPONSE, SDHCI_INT_STATUS); } static int sdhci_cmdq_crypto_cfg(struct mmc_host *mmc, struct mmc_request *mrq, u32 slot) struct mmc_request *mrq, u32 slot, u64 *ice_ctx) { struct sdhci_host *host = mmc_priv(mmc); int err = 0; Loading @@ -3794,7 +3794,8 @@ static int sdhci_cmdq_crypto_cfg(struct mmc_host *mmc, } if (host->ops->crypto_engine_cmdq_cfg) { err = host->ops->crypto_engine_cmdq_cfg(host, mrq, slot, NULL); err = host->ops->crypto_engine_cmdq_cfg(host, mrq, slot, ice_ctx); if (err) { pr_err("%s: failed to configure crypto\n", mmc_hostname(host->mmc)); Loading Loading @@ -3862,7 +3863,7 @@ static void sdhci_cmdq_post_cqe_halt(struct mmc_host *mmc) } static int sdhci_cmdq_crypto_cfg(struct mmc_host *mmc, struct mmc_request *mrq, u32 slot) struct mmc_request *mrq, u32 slot, u64 *ice_ctx) { return 0; } Loading Loading
drivers/mmc/host/cmdq_hci.c +130 −4 Original line number Diff line number Diff line Loading @@ -145,6 +145,29 @@ static void cmdq_clear_set_irqs(struct cmdq_host *cq_host, u32 clear, u32 set) mb(); } static int cmdq_clear_task_poll(struct cmdq_host *cq_host, unsigned int tag) { int retries = 100; cmdq_clear_set_irqs(cq_host, CQIS_TCL, 0); cmdq_writel(cq_host, 1<<tag, CQTCLR); while (retries) { /* * Task Clear register and doorbell, * both should indicate that task is cleared */ if ((cmdq_readl(cq_host, CQTCLR) & 1<<tag) || (cmdq_readl(cq_host, CQTDBR) & 1<<tag)) { udelay(5); retries--; continue; } else break; } cmdq_clear_set_irqs(cq_host, 0, CQIS_TCL); return retries ? 0 : -ETIMEDOUT; } #define DRV_NAME "cmdq-host" Loading Loading @@ -345,6 +368,7 @@ static int cmdq_enable(struct mmc_host *mmc) { int err = 0; u32 cqcfg; u32 cqcap = 0; bool dcmd_enable; struct cmdq_host *cq_host = mmc_cmdq_private(mmc); Loading Loading @@ -373,6 +397,18 @@ 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)); cqcap = cmdq_readl(cq_host, CQCAP); if (cqcap & CQCAP_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 |= CMDQ_CAP_CRYPTO_SUPPORT | CMDQ_TASK_DESC_SZ_128; cqcfg |= CQ_ICE_ENABLE; } cmdq_writel(cq_host, cqcfg, CQCFG); /* enable CQ_HOST */ cmdq_writel(cq_host, cmdq_readl(cq_host, CQCFG) | CQ_ENABLE, Loading Loading @@ -688,6 +724,30 @@ static void cmdq_prep_dcmd_desc(struct mmc_host *mmc, upper_32_bits(*task_desc)); } 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 = (__le64 *)((u8 *)task_desc + CQ_TASK_DESC_TASK_PARAMS_SIZE); 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 = cpu_to_le64(ice_ctx); } } static void cmdq_pm_qos_vote(struct sdhci_host *host, struct mmc_request *mrq) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); Loading @@ -711,6 +771,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", Loading @@ -730,7 +791,7 @@ static int cmdq_request(struct mmc_host *mmc, struct mmc_request *mrq) } if (cq_host->ops->crypto_cfg) { err = cq_host->ops->crypto_cfg(mmc, mrq, tag); 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); Loading @@ -743,6 +804,9 @@ static int cmdq_request(struct mmc_host *mmc, struct mmc_request *mrq) 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); Loading Loading @@ -787,7 +851,8 @@ static void cmdq_finish_data(struct mmc_host *mmc, unsigned int tag) CMDQ_SEND_STATUS_TRIGGER, CQ_VENDOR_CFG); cmdq_runtime_pm_put(cq_host); if (cq_host->ops->crypto_cfg_reset) if (!(cq_host->caps & CMDQ_CAP_CRYPTO_SUPPORT) && cq_host->ops->crypto_cfg_reset) cq_host->ops->crypto_cfg_reset(mmc, tag); mrq->done(mrq); } Loading @@ -801,6 +866,8 @@ irqreturn_t cmdq_irq(struct mmc_host *mmc, int err) struct mmc_request *mrq; int ret; u32 dbr_set = 0; u32 dev_pend_set = 0; int stat_err = 0; status = cmdq_readl(cq_host, CQIS); Loading @@ -809,7 +876,9 @@ irqreturn_t cmdq_irq(struct mmc_host *mmc, int err) MMC_TRACE(mmc, "%s: CQIS: 0x%x err: %d\n", __func__, status, err); if (err || (status & CQIS_RED)) { stat_err = status & (CQIS_RED | CQIS_GCE | CQIS_ICCE); if (err || stat_err) { err_info = cmdq_readl(cq_host, CQTERRI); pr_err("%s: err: %d status: 0x%08x task-err-info (0x%08lx)\n", mmc_hostname(mmc), err, status, err_info); Loading Loading @@ -912,7 +981,7 @@ irqreturn_t cmdq_irq(struct mmc_host *mmc, int err) * CQE detected a response error from device * In most cases, this would require a reset. */ if (status & CQIS_RED) { if (stat_err & CQIS_RED) { /* * will check if the RED error is due to a bkops * exception once the queue is empty Loading @@ -931,6 +1000,62 @@ irqreturn_t cmdq_irq(struct mmc_host *mmc, int err) mrq->cmdq_req->resp_arg = cmdq_readl(cq_host, CQCRA); } /* * Generic Crypto error detected by CQE. * Its a fatal, would require cmdq reset. */ if (stat_err & CQIS_GCE) { if (mrq->data) mrq->data->error = -EIO; pr_err("%s: Crypto generic error while processing task %lu!", mmc_hostname(mmc), tag); MMC_TRACE(mmc, "%s: GCE error detected with tag %lu\n", __func__, tag); } /* * Invalid crypto config error detected by CQE, clear the task. * Task can be cleared only when CQE is halt state. */ if (stat_err & CQIS_ICCE) { /* * Invalid Crypto Config Error is detected at the * beginning of the transfer before the actual execution * started. So just clear the task in CQE. No need to * clear in device. Only the task which caused ICCE has * to be cleared. Other tasks can be continue processing * The first task which is about to be prepared would * cause ICCE Error. */ dbr_set = cmdq_readl(cq_host, CQTDBR); dev_pend_set = cmdq_readl(cq_host, CQDPT); if (dbr_set ^ dev_pend_set) tag = ffs(dbr_set ^ dev_pend_set) - 1; mrq = get_req_by_tag(cq_host, tag); pr_err("%s: Crypto config error while processing task %lu!", mmc_hostname(mmc), tag); MMC_TRACE(mmc, "%s: ICCE error with tag %lu\n", __func__, tag); if (mrq->data) mrq->data->error = -EIO; else if (mrq->cmd) mrq->cmd->error = -EIO; /* * If CQE is halted and tag is valid then clear the task * then un-halt CQE and set flag to skip error recovery. * If any of the condtions is not met thene it will * enter into default error recovery path. */ if (!ret && (dbr_set ^ dev_pend_set)) { ret = cmdq_clear_task_poll(cq_host, tag); if (ret) { pr_err("%s: %s: task[%lu] clear failed ret=%d\n", mmc_hostname(mmc), __func__, tag, ret); } else if (!cmdq_halt_poll(mmc, false)) { mrq->cmdq_req->skip_err_handling = true; } } } cmdq_finish_data(mmc, tag); } else { cmdq_writel(cq_host, status, CQIS); Loading Loading @@ -1001,6 +1126,7 @@ static int cmdq_halt_poll(struct mmc_host *mmc, bool halt) cq_host->ops->clear_set_irqs(mmc, true); cmdq_writel(cq_host, cmdq_readl(cq_host, CQCTL) & ~HALT, CQCTL); mmc_host_clr_halt(mmc); return 0; } Loading
drivers/mmc/host/cmdq_hci.h +10 −2 Original line number Diff line number Diff line Loading @@ -18,11 +18,13 @@ #define CQVER 0x00 /* capabilities */ #define CQCAP 0x04 #define CQCAP_CS (1 << 28) /* configuration */ #define CQCFG 0x08 #define CQ_DCMD 0x00001000 #define CQ_TASK_DESC_SZ 0x00000100 #define CQ_ENABLE 0x00000001 #define CQ_ICE_ENABLE 0x00000002 /* control */ #define CQCTL 0x0C Loading @@ -35,6 +37,8 @@ #define CQIS_TCC (1 << 1) #define CQIS_RED (1 << 2) #define CQIS_TCL (1 << 3) #define CQIS_GCE (1 << 4) #define CQIS_ICCE (1 << 5) /* interrupt status enable */ #define CQISTE 0x14 Loading Loading @@ -110,7 +114,7 @@ /* command response argument */ #define CQCRA 0x5C #define CQ_INT_ALL 0xF #define CQ_INT_ALL 0x3F #define CQIC_DEFAULT_ICCTH 31 #define CQIC_DEFAULT_ICTOVAL 1 Loading Loading @@ -144,6 +148,9 @@ #define CQ_VENDOR_CFG 0x100 #define CMDQ_SEND_STATUS_TRIGGER (1 << 31) #define CQ_TASK_DESC_TASK_PARAMS_SIZE 8 #define CQ_TASK_DESC_ICE_PARAMS_SIZE 8 struct task_history { u64 task; bool is_dcmd; Loading @@ -161,6 +168,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 Loading Loading @@ -209,7 +217,7 @@ struct cmdq_host_ops { int (*reset)(struct mmc_host *mmc); void (*post_cqe_halt)(struct mmc_host *mmc); int (*crypto_cfg)(struct mmc_host *mmc, struct mmc_request *mrq, u32 slot); u32 slot, u64 *ice_ctx); void (*crypto_cfg_reset)(struct mmc_host *mmc, unsigned int slot); }; Loading
drivers/mmc/host/sdhci-msm-ice.c +68 −2 Original line number Diff line number Diff line Loading @@ -276,6 +276,58 @@ void sdhci_msm_ice_update_cfg(struct sdhci_host *host, u64 lba, mb(); } static inline void sdhci_msm_ice_hci_update_cmdq_cfg(u64 dun, unsigned int bypass, short key_index, u64 *ice_ctx) { /* * The naming convention got changed between ICE2.0 and ICE3.0 * registers fields. Below is the equivalent names for * ICE3.0 Vs ICE2.0: * Data Unit Number(DUN) == Logical Base address(LBA) * Crypto Configuration index (CCI) == Key Index * Crypto Enable (CE) == !BYPASS */ if (ice_ctx) *ice_ctx = DATA_UNIT_NUM(dun) | CRYPTO_CONFIG_INDEX(key_index) | CRYPTO_ENABLE(!bypass); } static void sdhci_msm_ice_hci_update_noncq_cfg(struct sdhci_host *host, u64 dun, unsigned int bypass, short key_index) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct sdhci_msm_host *msm_host = pltfm_host->priv; unsigned int crypto_params = 0; /* * The naming convention got changed between ICE2.0 and ICE3.0 * registers fields. Below is the equivalent names for * ICE3.0 Vs ICE2.0: * Data Unit Number(DUN) == Logical Base address(LBA) * Crypto Configuration index (CCI) == Key Index * Crypto Enable (CE) == !BYPASS */ /* Configure ICE bypass mode */ crypto_params |= (!bypass & MASK_SDHCI_MSM_ICE_HCI_PARAM_CE) << OFFSET_SDHCI_MSM_ICE_HCI_PARAM_CE; /* Configure Crypto Configure Index (CCI) */ crypto_params |= (key_index & MASK_SDHCI_MSM_ICE_HCI_PARAM_CCI) << OFFSET_SDHCI_MSM_ICE_HCI_PARAM_CCI; writel_relaxed((crypto_params & 0xFFFFFFFF), msm_host->cryptoio + ICE_NONCQ_CRYPTO_PARAMS); /* Update DUN */ writel_relaxed((dun & 0xFFFFFFFF), msm_host->cryptoio + ICE_NONCQ_CRYPTO_DUN); /* Ensure ICE registers are configured before issuing SDHCI request */ mb(); } int sdhci_msm_ice_cfg(struct sdhci_host *host, struct mmc_request *mrq, u32 slot) { Loading Loading @@ -308,7 +360,14 @@ int sdhci_msm_ice_cfg(struct sdhci_host *host, struct mmc_request *mrq, slot, bypass, key_index); } if (msm_host->ice_hci_support) { /* For ICE HCI / ICE3.0 */ sdhci_msm_ice_hci_update_noncq_cfg(host, lba, bypass, key_index); } else { /* For ICE versions earlier to ICE3.0 */ sdhci_msm_ice_update_cfg(host, lba, slot, bypass, key_index); } return 0; } Loading Loading @@ -344,7 +403,14 @@ int sdhci_msm_ice_cmdq_cfg(struct sdhci_host *host, slot, bypass, key_index); } if (msm_host->ice_hci_support) { /* For ICE HCI / ICE3.0 */ sdhci_msm_ice_hci_update_cmdq_cfg(lba, bypass, key_index, ice_ctx); } else { /* For ICE versions earlier to ICE3.0 */ sdhci_msm_ice_update_cfg(host, lba, slot, bypass, key_index); } return 0; } Loading
drivers/mmc/host/sdhci-msm-ice.h +8 −2 Original line number Diff line number Diff line Loading @@ -42,6 +42,8 @@ #define ICE_HCI_SUPPORT (1 << 28) #define ICE_CQ_CONFIG 0x08 #define CRYPTO_GENERAL_ENABLE (1 << 1) #define ICE_NONCQ_CRYPTO_PARAMS 0x70 #define ICE_NONCQ_CRYPTO_DUN 0x74 /* ICE3.0 register which got added hc reg space */ #define HC_VENDOR_SPECIFIC_FUNC4 0x260 Loading @@ -52,8 +54,10 @@ /* SDHCI MSM ICE CTRL Info register offset */ enum { OFFSET_SDHCI_MSM_ICE_CTRL_INFO_BYPASS = 0, OFFSET_SDHCI_MSM_ICE_CTRL_INFO_KEY_INDEX = 0x1, OFFSET_SDHCI_MSM_ICE_CTRL_INFO_CDU = 0x6, OFFSET_SDHCI_MSM_ICE_CTRL_INFO_KEY_INDEX = 1, OFFSET_SDHCI_MSM_ICE_CTRL_INFO_CDU = 6, OFFSET_SDHCI_MSM_ICE_HCI_PARAM_CCI = 0, OFFSET_SDHCI_MSM_ICE_HCI_PARAM_CE = 8, }; /* SDHCI MSM ICE CTRL Info register masks */ Loading @@ -61,6 +65,8 @@ enum { MASK_SDHCI_MSM_ICE_CTRL_INFO_BYPASS = 0x1, MASK_SDHCI_MSM_ICE_CTRL_INFO_KEY_INDEX = 0x1F, MASK_SDHCI_MSM_ICE_CTRL_INFO_CDU = 0x7, MASK_SDHCI_MSM_ICE_HCI_PARAM_CE = 0x1, MASK_SDHCI_MSM_ICE_HCI_PARAM_CCI = 0xff }; /* SDHCI MSM ICE encryption/decryption bypass state */ Loading
drivers/mmc/host/sdhci.c +4 −3 Original line number Diff line number Diff line Loading @@ -3775,7 +3775,7 @@ static void sdhci_cmdq_post_cqe_halt(struct mmc_host *mmc) sdhci_writel(host, SDHCI_INT_RESPONSE, SDHCI_INT_STATUS); } static int sdhci_cmdq_crypto_cfg(struct mmc_host *mmc, struct mmc_request *mrq, u32 slot) struct mmc_request *mrq, u32 slot, u64 *ice_ctx) { struct sdhci_host *host = mmc_priv(mmc); int err = 0; Loading @@ -3794,7 +3794,8 @@ static int sdhci_cmdq_crypto_cfg(struct mmc_host *mmc, } if (host->ops->crypto_engine_cmdq_cfg) { err = host->ops->crypto_engine_cmdq_cfg(host, mrq, slot, NULL); err = host->ops->crypto_engine_cmdq_cfg(host, mrq, slot, ice_ctx); if (err) { pr_err("%s: failed to configure crypto\n", mmc_hostname(host->mmc)); Loading Loading @@ -3862,7 +3863,7 @@ static void sdhci_cmdq_post_cqe_halt(struct mmc_host *mmc) } static int sdhci_cmdq_crypto_cfg(struct mmc_host *mmc, struct mmc_request *mrq, u32 slot) struct mmc_request *mrq, u32 slot, u64 *ice_ctx) { return 0; } Loading