Loading drivers/mmc/core/core.c +3 −0 Original line number Diff line number Diff line Loading @@ -3032,6 +3032,9 @@ void mmc_rescan(struct work_struct *work) if (freqs[i] <= host->f_min) break; } #if defined(CONFIG_SDC_QTI) host->err_stats[MMC_ERR_CMD_TIMEOUT] = 0; #endif mmc_release_host(host); out: Loading drivers/mmc/core/mmc_ops.c +8 −0 Original line number Diff line number Diff line Loading @@ -672,11 +672,19 @@ int mmc_send_tuning(struct mmc_host *host, u32 opcode, int *cmd_error) if (cmd.error) { err = cmd.error; #if defined(CONFIG_SDC_QTI) /* Ignore crc errors occurred during tuning */ if (host->err_stats[MMC_ERR_CMD_CRC]) host->err_stats[MMC_ERR_CMD_CRC]--; #endif goto out; } if (data.error) { err = data.error; #if defined(CONFIG_SDC_QTI) host->err_stats[MMC_ERR_DAT_CRC]--; #endif goto out; } Loading drivers/mmc/host/sdhci-msm.c +103 −1 Original line number Diff line number Diff line Loading @@ -3594,6 +3594,106 @@ static int sdhci_msm_setup_ice_clk(struct sdhci_msm_host *msm_host, return ret; } #if defined(CONFIG_SDC_QTI) static ssize_t err_state_show(struct device *dev, struct device_attribute *attr, char *buf) { struct sdhci_host *host = dev_get_drvdata(dev); if (!host || !host->mmc) return -EINVAL; return scnprintf(buf, PAGE_SIZE, "%d\n", !!host->mmc->err_occurred); } static ssize_t err_state_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct sdhci_host *host = dev_get_drvdata(dev); unsigned int val; if (kstrtouint(buf, 0, &val)) return -EINVAL; if (!host || !host->mmc) return -EINVAL; host->mmc->err_occurred = !!val; if (!val) memset(host->mmc->err_stats, 0, sizeof(host->mmc->err_stats)); return count; } static DEVICE_ATTR_RW(err_state); static ssize_t err_stats_show(struct device *dev, struct device_attribute *attr, char *buf) { struct sdhci_host *host = dev_get_drvdata(dev); char tmp[100]; if (!host || !host->mmc) return -EINVAL; scnprintf(tmp, sizeof(tmp), "# Command Timeout Error: %d\n", host->mmc->err_stats[MMC_ERR_CMD_TIMEOUT]); strlcpy(buf, tmp, PAGE_SIZE); scnprintf(tmp, sizeof(tmp), "# Command CRC Error: %d\n", host->mmc->err_stats[MMC_ERR_CMD_CRC]); strlcat(buf, tmp, PAGE_SIZE); scnprintf(tmp, sizeof(tmp), "# Data Timeout Error: %d\n", host->mmc->err_stats[MMC_ERR_DAT_TIMEOUT]); strlcat(buf, tmp, PAGE_SIZE); scnprintf(tmp, sizeof(tmp), "# Data CRC Error: %d\n", host->mmc->err_stats[MMC_ERR_DAT_CRC]); strlcat(buf, tmp, PAGE_SIZE); scnprintf(tmp, sizeof(tmp), "# Auto-Cmd Error: %d\n", host->mmc->err_stats[MMC_ERR_ADMA]); strlcat(buf, tmp, PAGE_SIZE); scnprintf(tmp, sizeof(tmp), "# ADMA Error: %d\n", host->mmc->err_stats[MMC_ERR_ADMA]); strlcat(buf, tmp, PAGE_SIZE); scnprintf(tmp, sizeof(tmp), "# Tuning Error: %d\n", host->mmc->err_stats[MMC_ERR_TUNING]); strlcat(buf, tmp, PAGE_SIZE); scnprintf(tmp, sizeof(tmp), "# Request Timedout Error: %d\n", host->mmc->err_stats[MMC_ERR_REQ_TIMEOUT]); strlcat(buf, tmp, PAGE_SIZE); return strlen(buf); } static DEVICE_ATTR_RO(err_stats); static struct attribute *sdhci_msm_sysfs_attrs[] = { &dev_attr_err_state.attr, &dev_attr_err_stats.attr, NULL }; static const struct attribute_group sdhci_msm_sysfs_group = { .name = "qcom", .attrs = sdhci_msm_sysfs_attrs, }; static int sdhci_msm_init_sysfs(struct platform_device *pdev) { int ret; ret = sysfs_create_group(&pdev->dev.kobj, &sdhci_msm_sysfs_group); if (ret) dev_err(&pdev->dev, "%s: Failed sdhci_msm sysfs group err=%d\n", __func__, ret); return ret; } #endif static int sdhci_msm_probe(struct platform_device *pdev) { struct sdhci_host *host; Loading Loading @@ -3868,7 +3968,9 @@ static int sdhci_msm_probe(struct platform_device *pdev) * value won't be over-written. */ host->mmc->max_busy_timeout = 0; #if defined(CONFIG_SDC_QTI) sdhci_msm_init_sysfs(pdev); #endif /* * Set platfm_init_done only after sdhci_add_host(). * So that we don't turn off vqmmc while we reset sdhc as Loading drivers/mmc/host/sdhci.c +37 −7 Original line number Diff line number Diff line Loading @@ -108,7 +108,9 @@ void sdhci_dumpregs(struct sdhci_host *host) sdhci_readl(host, SDHCI_ADMA_ADDRESS)); } } #if defined(CONFIG_SDC_QTI) host->mmc->err_occurred = true; #endif SDHCI_DUMP("============================================\n"); } EXPORT_SYMBOL_GPL(sdhci_dumpregs); Loading Loading @@ -2880,6 +2882,9 @@ static void sdhci_timeout_timer(struct timer_list *t) spin_lock_irqsave(&host->lock, flags); if (host->cmd && !sdhci_data_line_cmd(host->cmd)) { #if defined(CONFIG_SDC_QTI) host->mmc->err_stats[MMC_ERR_REQ_TIMEOUT]++; #endif pr_err("%s: Timeout waiting for hardware cmd interrupt.\n", mmc_hostname(host->mmc)); sdhci_dumpregs(host); Loading @@ -2902,6 +2907,9 @@ static void sdhci_timeout_data_timer(struct timer_list *t) if (host->data || host->data_cmd || (host->cmd && sdhci_data_line_cmd(host->cmd))) { #if defined(CONFIG_SDC_QTI) host->mmc->err_stats[MMC_ERR_REQ_TIMEOUT]++; #endif pr_err("%s: Timeout waiting for hardware interrupt.\n", mmc_hostname(host->mmc)); sdhci_dumpregs(host); Loading Loading @@ -2961,11 +2969,17 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *intmask_p) if (intmask & (SDHCI_INT_TIMEOUT | SDHCI_INT_CRC | SDHCI_INT_END_BIT | SDHCI_INT_INDEX)) { if (intmask & SDHCI_INT_TIMEOUT) if (intmask & SDHCI_INT_TIMEOUT) { host->cmd->error = -ETIMEDOUT; else #if defined(CONFIG_SDC_QTI) host->mmc->err_stats[MMC_ERR_CMD_TIMEOUT]++; #endif } else { host->cmd->error = -EILSEQ; #if defined(CONFIG_SDC_QTI) host->mmc->err_stats[MMC_ERR_CMD_CRC]++; #endif } /* Treat data command CRC error the same as data CRC error */ if (host->cmd->data && (intmask & (SDHCI_INT_CRC | SDHCI_INT_TIMEOUT)) == Loading @@ -2986,7 +3000,9 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *intmask_p) int err = (auto_cmd_status & SDHCI_AUTO_CMD_TIMEOUT) ? -ETIMEDOUT : -EILSEQ; #if defined(CONFIG_SDC_QTI) host->mmc->err_stats[MMC_ERR_AUTO_CMD]++; #endif if (mrq->sbc && (host->flags & SDHCI_AUTO_CMD23)) { mrq->sbc->error = err; __sdhci_finish_mrq(host, mrq); Loading Loading @@ -3057,6 +3073,9 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) if (intmask & SDHCI_INT_DATA_TIMEOUT) { host->data_cmd = NULL; data_cmd->error = -ETIMEDOUT; #if defined(CONFIG_SDC_QTI) host->mmc->err_stats[MMC_ERR_CMD_TIMEOUT]++; #endif __sdhci_finish_mrq(host, data_cmd->mrq); return; } Loading Loading @@ -3090,18 +3109,29 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) return; } if (intmask & SDHCI_INT_DATA_TIMEOUT) if (intmask & SDHCI_INT_DATA_TIMEOUT) { host->data->error = -ETIMEDOUT; #if defined(CONFIG_SDC_QTI) host->mmc->err_stats[MMC_ERR_DAT_TIMEOUT]++; #endif } else if (intmask & SDHCI_INT_DATA_END_BIT) host->data->error = -EILSEQ; else if ((intmask & SDHCI_INT_DATA_CRC) && SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)) != MMC_BUS_TEST_R) != MMC_BUS_TEST_R) { host->data->error = -EILSEQ; #if defined(CONFIG_SDC_QTI) host->mmc->err_stats[MMC_ERR_DAT_CRC]++; #endif } else if (intmask & SDHCI_INT_ADMA_ERROR) { pr_err("%s: ADMA error: 0x%08x\n", mmc_hostname(host->mmc), intmask); sdhci_adma_show_error(host); #if defined(CONFIG_SDC_QTI) host->mmc->err_stats[MMC_ERR_ADMA]++; #endif host->data->error = -EIO; if (host->ops->adma_workaround) host->ops->adma_workaround(host, intmask); Loading include/linux/mmc/host.h +23 −1 Original line number Diff line number Diff line Loading @@ -82,6 +82,25 @@ struct mmc_ios { struct mmc_host; #if defined(CONFIG_SDC_QTI) enum { MMC_ERR_CMD_TIMEOUT, MMC_ERR_CMD_CRC, MMC_ERR_DAT_TIMEOUT, MMC_ERR_DAT_CRC, MMC_ERR_AUTO_CMD, MMC_ERR_ADMA, MMC_ERR_TUNING, MMC_ERR_CMDQ_RED, MMC_ERR_CMDQ_GCE, MMC_ERR_CMDQ_ICCE, MMC_ERR_REQ_TIMEOUT, MMC_ERR_CMDQ_REQ_TIMEOUT, MMC_ERR_ICE_CFG, MMC_ERR_MAX, }; #endif struct mmc_host_ops { /* * It is optional for the host to implement pre_req and post_req in Loading Loading @@ -518,7 +537,10 @@ struct mmc_host { struct mmc_supply supply; struct dentry *debugfs_root; #if defined(CONFIG_SDC_QTI) bool err_occurred; u32 err_stats[MMC_ERR_MAX]; #endif /* Ongoing data transfer that allows commands during transfer */ struct mmc_request *ongoing_mrq; Loading Loading
drivers/mmc/core/core.c +3 −0 Original line number Diff line number Diff line Loading @@ -3032,6 +3032,9 @@ void mmc_rescan(struct work_struct *work) if (freqs[i] <= host->f_min) break; } #if defined(CONFIG_SDC_QTI) host->err_stats[MMC_ERR_CMD_TIMEOUT] = 0; #endif mmc_release_host(host); out: Loading
drivers/mmc/core/mmc_ops.c +8 −0 Original line number Diff line number Diff line Loading @@ -672,11 +672,19 @@ int mmc_send_tuning(struct mmc_host *host, u32 opcode, int *cmd_error) if (cmd.error) { err = cmd.error; #if defined(CONFIG_SDC_QTI) /* Ignore crc errors occurred during tuning */ if (host->err_stats[MMC_ERR_CMD_CRC]) host->err_stats[MMC_ERR_CMD_CRC]--; #endif goto out; } if (data.error) { err = data.error; #if defined(CONFIG_SDC_QTI) host->err_stats[MMC_ERR_DAT_CRC]--; #endif goto out; } Loading
drivers/mmc/host/sdhci-msm.c +103 −1 Original line number Diff line number Diff line Loading @@ -3594,6 +3594,106 @@ static int sdhci_msm_setup_ice_clk(struct sdhci_msm_host *msm_host, return ret; } #if defined(CONFIG_SDC_QTI) static ssize_t err_state_show(struct device *dev, struct device_attribute *attr, char *buf) { struct sdhci_host *host = dev_get_drvdata(dev); if (!host || !host->mmc) return -EINVAL; return scnprintf(buf, PAGE_SIZE, "%d\n", !!host->mmc->err_occurred); } static ssize_t err_state_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct sdhci_host *host = dev_get_drvdata(dev); unsigned int val; if (kstrtouint(buf, 0, &val)) return -EINVAL; if (!host || !host->mmc) return -EINVAL; host->mmc->err_occurred = !!val; if (!val) memset(host->mmc->err_stats, 0, sizeof(host->mmc->err_stats)); return count; } static DEVICE_ATTR_RW(err_state); static ssize_t err_stats_show(struct device *dev, struct device_attribute *attr, char *buf) { struct sdhci_host *host = dev_get_drvdata(dev); char tmp[100]; if (!host || !host->mmc) return -EINVAL; scnprintf(tmp, sizeof(tmp), "# Command Timeout Error: %d\n", host->mmc->err_stats[MMC_ERR_CMD_TIMEOUT]); strlcpy(buf, tmp, PAGE_SIZE); scnprintf(tmp, sizeof(tmp), "# Command CRC Error: %d\n", host->mmc->err_stats[MMC_ERR_CMD_CRC]); strlcat(buf, tmp, PAGE_SIZE); scnprintf(tmp, sizeof(tmp), "# Data Timeout Error: %d\n", host->mmc->err_stats[MMC_ERR_DAT_TIMEOUT]); strlcat(buf, tmp, PAGE_SIZE); scnprintf(tmp, sizeof(tmp), "# Data CRC Error: %d\n", host->mmc->err_stats[MMC_ERR_DAT_CRC]); strlcat(buf, tmp, PAGE_SIZE); scnprintf(tmp, sizeof(tmp), "# Auto-Cmd Error: %d\n", host->mmc->err_stats[MMC_ERR_ADMA]); strlcat(buf, tmp, PAGE_SIZE); scnprintf(tmp, sizeof(tmp), "# ADMA Error: %d\n", host->mmc->err_stats[MMC_ERR_ADMA]); strlcat(buf, tmp, PAGE_SIZE); scnprintf(tmp, sizeof(tmp), "# Tuning Error: %d\n", host->mmc->err_stats[MMC_ERR_TUNING]); strlcat(buf, tmp, PAGE_SIZE); scnprintf(tmp, sizeof(tmp), "# Request Timedout Error: %d\n", host->mmc->err_stats[MMC_ERR_REQ_TIMEOUT]); strlcat(buf, tmp, PAGE_SIZE); return strlen(buf); } static DEVICE_ATTR_RO(err_stats); static struct attribute *sdhci_msm_sysfs_attrs[] = { &dev_attr_err_state.attr, &dev_attr_err_stats.attr, NULL }; static const struct attribute_group sdhci_msm_sysfs_group = { .name = "qcom", .attrs = sdhci_msm_sysfs_attrs, }; static int sdhci_msm_init_sysfs(struct platform_device *pdev) { int ret; ret = sysfs_create_group(&pdev->dev.kobj, &sdhci_msm_sysfs_group); if (ret) dev_err(&pdev->dev, "%s: Failed sdhci_msm sysfs group err=%d\n", __func__, ret); return ret; } #endif static int sdhci_msm_probe(struct platform_device *pdev) { struct sdhci_host *host; Loading Loading @@ -3868,7 +3968,9 @@ static int sdhci_msm_probe(struct platform_device *pdev) * value won't be over-written. */ host->mmc->max_busy_timeout = 0; #if defined(CONFIG_SDC_QTI) sdhci_msm_init_sysfs(pdev); #endif /* * Set platfm_init_done only after sdhci_add_host(). * So that we don't turn off vqmmc while we reset sdhc as Loading
drivers/mmc/host/sdhci.c +37 −7 Original line number Diff line number Diff line Loading @@ -108,7 +108,9 @@ void sdhci_dumpregs(struct sdhci_host *host) sdhci_readl(host, SDHCI_ADMA_ADDRESS)); } } #if defined(CONFIG_SDC_QTI) host->mmc->err_occurred = true; #endif SDHCI_DUMP("============================================\n"); } EXPORT_SYMBOL_GPL(sdhci_dumpregs); Loading Loading @@ -2880,6 +2882,9 @@ static void sdhci_timeout_timer(struct timer_list *t) spin_lock_irqsave(&host->lock, flags); if (host->cmd && !sdhci_data_line_cmd(host->cmd)) { #if defined(CONFIG_SDC_QTI) host->mmc->err_stats[MMC_ERR_REQ_TIMEOUT]++; #endif pr_err("%s: Timeout waiting for hardware cmd interrupt.\n", mmc_hostname(host->mmc)); sdhci_dumpregs(host); Loading @@ -2902,6 +2907,9 @@ static void sdhci_timeout_data_timer(struct timer_list *t) if (host->data || host->data_cmd || (host->cmd && sdhci_data_line_cmd(host->cmd))) { #if defined(CONFIG_SDC_QTI) host->mmc->err_stats[MMC_ERR_REQ_TIMEOUT]++; #endif pr_err("%s: Timeout waiting for hardware interrupt.\n", mmc_hostname(host->mmc)); sdhci_dumpregs(host); Loading Loading @@ -2961,11 +2969,17 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *intmask_p) if (intmask & (SDHCI_INT_TIMEOUT | SDHCI_INT_CRC | SDHCI_INT_END_BIT | SDHCI_INT_INDEX)) { if (intmask & SDHCI_INT_TIMEOUT) if (intmask & SDHCI_INT_TIMEOUT) { host->cmd->error = -ETIMEDOUT; else #if defined(CONFIG_SDC_QTI) host->mmc->err_stats[MMC_ERR_CMD_TIMEOUT]++; #endif } else { host->cmd->error = -EILSEQ; #if defined(CONFIG_SDC_QTI) host->mmc->err_stats[MMC_ERR_CMD_CRC]++; #endif } /* Treat data command CRC error the same as data CRC error */ if (host->cmd->data && (intmask & (SDHCI_INT_CRC | SDHCI_INT_TIMEOUT)) == Loading @@ -2986,7 +3000,9 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *intmask_p) int err = (auto_cmd_status & SDHCI_AUTO_CMD_TIMEOUT) ? -ETIMEDOUT : -EILSEQ; #if defined(CONFIG_SDC_QTI) host->mmc->err_stats[MMC_ERR_AUTO_CMD]++; #endif if (mrq->sbc && (host->flags & SDHCI_AUTO_CMD23)) { mrq->sbc->error = err; __sdhci_finish_mrq(host, mrq); Loading Loading @@ -3057,6 +3073,9 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) if (intmask & SDHCI_INT_DATA_TIMEOUT) { host->data_cmd = NULL; data_cmd->error = -ETIMEDOUT; #if defined(CONFIG_SDC_QTI) host->mmc->err_stats[MMC_ERR_CMD_TIMEOUT]++; #endif __sdhci_finish_mrq(host, data_cmd->mrq); return; } Loading Loading @@ -3090,18 +3109,29 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) return; } if (intmask & SDHCI_INT_DATA_TIMEOUT) if (intmask & SDHCI_INT_DATA_TIMEOUT) { host->data->error = -ETIMEDOUT; #if defined(CONFIG_SDC_QTI) host->mmc->err_stats[MMC_ERR_DAT_TIMEOUT]++; #endif } else if (intmask & SDHCI_INT_DATA_END_BIT) host->data->error = -EILSEQ; else if ((intmask & SDHCI_INT_DATA_CRC) && SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)) != MMC_BUS_TEST_R) != MMC_BUS_TEST_R) { host->data->error = -EILSEQ; #if defined(CONFIG_SDC_QTI) host->mmc->err_stats[MMC_ERR_DAT_CRC]++; #endif } else if (intmask & SDHCI_INT_ADMA_ERROR) { pr_err("%s: ADMA error: 0x%08x\n", mmc_hostname(host->mmc), intmask); sdhci_adma_show_error(host); #if defined(CONFIG_SDC_QTI) host->mmc->err_stats[MMC_ERR_ADMA]++; #endif host->data->error = -EIO; if (host->ops->adma_workaround) host->ops->adma_workaround(host, intmask); Loading
include/linux/mmc/host.h +23 −1 Original line number Diff line number Diff line Loading @@ -82,6 +82,25 @@ struct mmc_ios { struct mmc_host; #if defined(CONFIG_SDC_QTI) enum { MMC_ERR_CMD_TIMEOUT, MMC_ERR_CMD_CRC, MMC_ERR_DAT_TIMEOUT, MMC_ERR_DAT_CRC, MMC_ERR_AUTO_CMD, MMC_ERR_ADMA, MMC_ERR_TUNING, MMC_ERR_CMDQ_RED, MMC_ERR_CMDQ_GCE, MMC_ERR_CMDQ_ICCE, MMC_ERR_REQ_TIMEOUT, MMC_ERR_CMDQ_REQ_TIMEOUT, MMC_ERR_ICE_CFG, MMC_ERR_MAX, }; #endif struct mmc_host_ops { /* * It is optional for the host to implement pre_req and post_req in Loading Loading @@ -518,7 +537,10 @@ struct mmc_host { struct mmc_supply supply; struct dentry *debugfs_root; #if defined(CONFIG_SDC_QTI) bool err_occurred; u32 err_stats[MMC_ERR_MAX]; #endif /* Ongoing data transfer that allows commands during transfer */ struct mmc_request *ongoing_mrq; Loading