Re: SDHCI regression since 2.6.39

Jeremy Fitzhardinge
2011-09-13T17:00:24Z

On 09/13/2011 06:22 AM, Chris Ball wrote:
> Hi Jeremy,
>
> On Mon, Sep 12 2011, Jeremy Fitzhardinge wrote:
>> Since 2.6.39, the SD card slot in my Lenovo X220 has stopped working.
>> When I insert a card with current linux.git kernel (3.1-rc6), I get:
>>
>> [ 3891.745549] mmc0: new SDHC card at address b368
>> [ 3891.790704] mmcblk0: mmc0:b368 PNY 7.51 GiB
>> [ 3891.795568] mmc0: Got data interrupt 0x00200000 even though no data
>> operation was in progress.
> Please could you try reverting a3c7778f8153b9 "mmc: sdhci: R1B command
> handling + MMC_CAP_ERASE"? We've had one other similar report that
> bisected to this patch.
>

The revert was not entirely trivial (below), but I'm fairly sure I got
it right, and it didn't help.

On card insert, it now says:

[56549.455385] mmc0: new SDHC card at address b368
[56549.456872] mmcblk0: mmc0:b368 PNY 7.51 GiB
[56549.467279] mmc0: starting CMD18 arg 00000000 flags 000000b5
[56549.467288] mmc0: blksz 512 blocks 8 flags 00000200 tsac 100 ms nsac 0
[56549.467294] mmc0: CMD12 arg 00000000 flags 0000049d
[56549.467340] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00018000
[56549.467369] mmc0: req done (CMD18): -110: 00000000 00000000 00000000 00000000
[56549.467376] mmc0: 0 bytes transferred: 0
[56549.467382] mmc0: (CMD12): 0: 00000000 00000000 00000000 00000000
[56549.467404] mmc0: starting CMD13 arg b3680000 flags 00000195
[56549.467440] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00018000
[56549.467455] mmc0: req done (CMD13): -110: 00000000 00000000 00000000 00000000
[56549.467458] mmcblk0: error -110 sending status command, retrying
[56549.467461] mmc0: starting CMD13 arg b3680000 flags 00000195
[56549.467477] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00000001
[56549.467484] mmc0: req done (CMD13): 0: 00800900 00000000 00000000 00000000
[56549.467488] mmcblk0: timed out sending r/w cmd command, card status 0x800900
[56549.467492] mmc0: starting CMD18 arg 00000000 flags 000000b5
[56549.467494] mmc0: blksz 512 blocks 8 flags 00000200 tsac 100 ms nsac 0
[56549.467496] mmc0: CMD12 arg 00000000 flags 0000049d
[56549.467518] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00000001
[56549.467973] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00608000
[56549.468019] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00408003
[56549.468035] mmc0: req done (CMD18): 0: 00000900 00000000 00000000 00000000
[56549.468037] mmc0: 0 bytes transferred: -84
[56549.468038] mmc0: (CMD12): 0: 00000b00 00000000 00000000 00000000
[56549.468045] mmcblk0: error -84 transferring data, sector 0, nr 8, cmd response 0x900, card status 0xb00
[56549.468047] mmcblk0: retrying using single block read
[56549.468051] mmc0: starting CMD17 arg 00000000 flags 000000b5
[56549.468053] mmc0: blksz 512 blocks 1 flags 00000200 tsac 100 ms nsac 0
[56549.468076] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00000001
[56549.468411] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00608002
[56549.468438] mmc0: req done (CMD17): 0: 00000900 00000000 00000000 00000000
[56549.468444] mmc0: 0 bytes transferred: -84
[56549.468459] mmcblk0: error -84 transferring data, sector 0, nr 8, cmd response 0x900, card status 0x0
[56549.468471] end_request: I/O error, dev mmcblk0, sector 0
[56549.468481] mmc0: starting CMD17 arg 00000001 flags 000000b5
[56549.468488] mmc0: blksz 512 blocks 1 flags 00000200 tsac 100 ms nsac 0
[56549.468525] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00000001
[56549.468855] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00408002
[56549.468881] mmc0: req done (CMD17): 0: 00000900 00000000 00000000 00000000
[56549.468887] mmc0: 0 bytes transferred: -84
[56549.468902] mmcblk0: error -84 transferring data, sector 1, nr 7, cmd response 0x900, card status 0x0
[56549.468928] end_request: I/O error, dev mmcblk0, sector 1
[56549.468931] mmc0: starting CMD17 arg 00000002 flags 000000b5
[56549.468934] mmc0: blksz 512 blocks 1 flags 00000200 tsac 100 ms nsac 0
[56549.468958] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00000001
[56549.469295] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00000002
[56549.469311] mmc0: req done (CMD17): 0: 00000900 00000000 00000000 00000000
[56549.469318] mmc0: 512 bytes transferred: 0
[56549.469340] mmc0: starting CMD17 arg 00000003 flags 000000b5
[56549.469347] mmc0: blksz 512 blocks 1 flags 00000200 tsac 100 ms nsac 0
[56549.469382] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00000001
[56549.469714] sdhci [sdhci_irq()]: *** mmc0 got interrupt: 0x00000002
[...]

Thanks,
J

Revert patch:
index 0e02cc1..7d85245 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -42,6 +42,7 @@

static unsigned int debug_quirks = 0;

+static void sdhci_prepare_data(struct sdhci_host *, struct mmc_data *);
static void sdhci_finish_data(struct sdhci_host *);

static void sdhci_send_command(struct sdhci_host *, struct mmc_command *);
@@ -606,10 +607,9 @@ static void sdhci_adma_table_post(struct sdhci_host *host,
data->sg_len, direction);
}

-static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd)
+static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_data *data)
{
u8 count;
- struct mmc_data *data = cmd->data;
unsigned target_timeout, current_timeout;

/*
@@ -621,18 +621,12 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd)
if (host->quirks & SDHCI_QUIRK_BROKEN_TIMEOUT_VAL)
return 0xE;

- /* Unspecified timeout, assume max */
- if (!data && !cmd->cmd_timeout_ms)
- return 0xE;
-
/* timeout in us */
- if (!data)
- target_timeout = cmd->cmd_timeout_ms * 1000;
- else {
- target_timeout = data->timeout_ns / 1000;
- if (host->clock)
- target_timeout += data->timeout_clks / host->clock;
- }
+ target_timeout = data->timeout_ns / 1000 +
+ data->timeout_clks / host->clock;
+
+ if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)
+ host->timeout_clk = host->clock / 1000;

/*
* Figure out needed cycles.
@@ -654,8 +648,8 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd)
}

if (count >= 0xF) {
- printk(KERN_WARNING "%s: Too large timeout requested for CMD%d!\n",
- mmc_hostname(host->mmc), cmd->opcode);
+ printk(KERN_WARNING "%s: Too large timeout requested!\n",
+ mmc_hostname(host->mmc));
count = 0xE;
}

@@ -673,21 +667,15 @@ static void sdhci_set_transfer_irqs(struct sdhci_host *host)
sdhci_clear_set_irqs(host, dma_irqs, pio_irqs);
}

-static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)
+static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
{
u8 count;
u8 ctrl;
- struct mmc_data *data = cmd->data;
int ret;

WARN_ON(host->data);

- if (data || (cmd->flags & MMC_RSP_BUSY)) {
- count = sdhci_calc_timeout(host, cmd);
- sdhci_writeb(host, count, SDHCI_TIMEOUT_CONTROL);
- }
-
- if (!data)
+ if (data == NULL)
return;

/* Sanity checks */
@@ -699,6 +687,9 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)
host->data_early = 0;
host->data->bytes_xfered = 0;

+ count = sdhci_calc_timeout(host, data);
+ sdhci_writeb(host, count, SDHCI_TIMEOUT_CONTROL);
+
if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA))
host->flags |= SDHCI_REQ_USE_DMA;

@@ -964,7 +955,7 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)

host->cmd = cmd;

- sdhci_prepare_data(host, cmd);
+ sdhci_prepare_data(host, cmd->data);

sdhci_writel(host, cmd->arg, SDHCI_ARGUMENT);

@@ -2504,12 +2495,9 @@ int sdhci_add_host(struct sdhci_host *host)
if (caps[0] & SDHCI_TIMEOUT_CLK_UNIT)
host->timeout_clk *= 1000;

- if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)
- host->timeout_clk = mmc->f_max / 1000;
-
mmc->max_discard_to = (1 << 27) / host->timeout_clk;

- mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23;
+ mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_CMD23;

if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12)
host->flags |= SDHCI_AUTO_CMD12;