Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ershephe/update tuning error handling 6.6 nr #190

Draft
wants to merge 4 commits into
base: nilrt/master/6.6
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion drivers/mmc/core/sd.c
Original file line number Diff line number Diff line change
Expand Up @@ -668,7 +668,8 @@ static int mmc_sd_init_uhs_card(struct mmc_card *card)
if (!mmc_host_is_spi(card->host) &&
(card->host->ios.timing == MMC_TIMING_UHS_SDR50 ||
card->host->ios.timing == MMC_TIMING_UHS_DDR50 ||
card->host->ios.timing == MMC_TIMING_UHS_SDR104)) {
card->host->ios.timing == MMC_TIMING_UHS_SDR104) &&
!card->host->skip_init_tune) {
err = mmc_execute_tuning(card);

/*
Expand All @@ -681,6 +682,7 @@ static int mmc_sd_init_uhs_card(struct mmc_card *card)
if (err && card->host->ios.timing == MMC_TIMING_UHS_DDR50) {
pr_warn("%s: ddr50 tuning failed\n",
mmc_hostname(card->host));
card->host->skip_init_tune = 1;
err = 0;
}
}
Expand Down
37 changes: 12 additions & 25 deletions drivers/mmc/host/sdhci.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
#include <linux/mmc/sdio.h>
#include <linux/mmc/slot-gpio.h>

#include "../core/host.h"
#include "sdhci.h"

#define DRIVER_NAME "sdhci"
Expand Down Expand Up @@ -305,7 +304,7 @@ static void sdhci_set_default_irqs(struct sdhci_host *host)

if (host->tuning_mode == SDHCI_TUNING_MODE_2 ||
host->tuning_mode == SDHCI_TUNING_MODE_3)
host->ier |= SDHCI_INT_RETUNE | SDHCI_INT_TUNING_ERR;
host->ier |= SDHCI_INT_RETUNE;

sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
Expand Down Expand Up @@ -2951,7 +2950,8 @@ int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)

sdhci_start_tuning(host);

host->tuning_err = __sdhci_execute_tuning(host, opcode);
err = __sdhci_execute_tuning(host, opcode);
host->tuning_err = err;

sdhci_end_tuning(host);
out:
Expand Down Expand Up @@ -3450,12 +3450,18 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
host->data->error = -EILSEQ;
if (!mmc_op_tuning(SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND))))
sdhci_err_stats_inc(host, DAT_CRC);
} else if ((intmask & SDHCI_INT_DATA_CRC) &&
} else if ((intmask & (SDHCI_INT_DATA_CRC | SDHCI_INT_TUNING_ERROR)) &&
SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND))
!= MMC_BUS_TEST_R) {
host->data->error = -EILSEQ;
if (!mmc_op_tuning(SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND))))
sdhci_err_stats_inc(host, DAT_CRC);
if (intmask & SDHCI_INT_TUNING_ERROR) {
u16 ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);

ctrl2 &= ~SDHCI_CTRL_TUNED_CLK;
sdhci_writew(host, ctrl2, SDHCI_HOST_CONTROL2);
}
} else if (intmask & SDHCI_INT_ADMA_ERROR) {
pr_err("%s: ADMA error: 0x%08x\n", mmc_hostname(host->mmc),
intmask);
Expand Down Expand Up @@ -3602,24 +3608,6 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
if (intmask & SDHCI_INT_RETUNE)
mmc_retune_needed(host->mmc);

if (intmask & SDHCI_INT_TUNING_ERR) {
u16 ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
/*
* Only complain and retune if we're actually using the
* host's tuning circuits.
*/
if (ctrl2 & SDHCI_CTRL_TUNED_CLK) {
sdhci_writew(host,
ctrl2 & ~SDHCI_CTRL_TUNED_CLK,
SDHCI_HOST_CONTROL2);
mmc_retune_recheck(host->mmc);
pr_err("%s: Unrecoverable error in tuning circuit\n",
mmc_hostname(host->mmc));
}
sdhci_writel(host, SDHCI_INT_TUNING_ERR,
SDHCI_INT_STATUS);
}

if ((intmask & SDHCI_INT_CARD_INT) &&
(host->ier & SDHCI_INT_CARD_INT)) {
sdhci_enable_sdio_irq_nolock(host, false);
Expand All @@ -3629,8 +3617,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE |
SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK |
SDHCI_INT_ERROR | SDHCI_INT_BUS_POWER |
SDHCI_INT_RETUNE | SDHCI_INT_TUNING_ERR |
SDHCI_INT_CARD_INT);
SDHCI_INT_RETUNE | SDHCI_INT_CARD_INT);

if (intmask) {
unexpected |= intmask;
Expand Down Expand Up @@ -4009,7 +3996,7 @@ bool sdhci_cqe_irq(struct sdhci_host *host, u32 intmask, int *cmd_error,
} else
*cmd_error = 0;

if (intmask & (SDHCI_INT_DATA_END_BIT | SDHCI_INT_DATA_CRC)) {
if (intmask & (SDHCI_INT_DATA_END_BIT | SDHCI_INT_DATA_CRC | SDHCI_INT_TUNING_ERROR)) {
*data_error = -EILSEQ;
if (!mmc_op_tuning(SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND))))
sdhci_err_stats_inc(host, DAT_CRC);
Expand Down
4 changes: 2 additions & 2 deletions drivers/mmc/host/sdhci.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@
#define SDHCI_INT_BUS_POWER 0x00800000
#define SDHCI_INT_AUTO_CMD_ERR 0x01000000
#define SDHCI_INT_ADMA_ERROR 0x02000000
#define SDHCI_INT_TUNING_ERR 0x04000000
#define SDHCI_INT_TUNING_ERROR 0x04000000
erickshepherdNI marked this conversation as resolved.
Show resolved Hide resolved

#define SDHCI_INT_NORMAL_MASK 0x00007FFF
#define SDHCI_INT_ERROR_MASK 0xFFFF8000
Expand All @@ -170,7 +170,7 @@
SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | \
SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | \
SDHCI_INT_DATA_END_BIT | SDHCI_INT_ADMA_ERROR | \
SDHCI_INT_BLK_GAP)
SDHCI_INT_BLK_GAP | SDHCI_INT_TUNING_ERROR)
#define SDHCI_INT_ALL_MASK ((unsigned int)-1)

#define SDHCI_CQE_INT_ERR_MASK ( \
Expand Down
1 change: 1 addition & 0 deletions include/linux/mmc/host.h
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,7 @@ struct mmc_host {
unsigned int use_spi_crc:1;
unsigned int claimed:1; /* host exclusively claimed */
unsigned int doing_init_tune:1; /* initial tuning in progress */
unsigned int skip_init_tune:1; /* skip the initial tuning */
unsigned int can_retune:1; /* re-tuning can be used */
unsigned int doing_retune:1; /* re-tuning in progress */
unsigned int retune_now:1; /* do re-tuning at next req */
Expand Down