From 0c62873e21fd9a7902c16d146c9464ee6b591bb0 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sun, 12 Aug 2007 16:46:32 +0200 Subject: [PATCH] --- yaml --- r: 64334 b: refs/heads/master c: e538fbe83e374a3521128c1f4642aca037661c9d h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/drivers/mmc/host/sdhci.c | 28 +++++++++++++++++++++------- trunk/drivers/mmc/host/sdhci.h | 1 + 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/[refs] b/[refs] index 04e4e9a54510..aaca9890b7b8 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 03f8590d90844f04d20488a80e75eaf4c4e0b35c +refs/heads/master: e538fbe83e374a3521128c1f4642aca037661c9d diff --git a/trunk/drivers/mmc/host/sdhci.c b/trunk/drivers/mmc/host/sdhci.c index 2b327b40fa81..f8fc0a98b8c4 100644 --- a/trunk/drivers/mmc/host/sdhci.c +++ b/trunk/drivers/mmc/host/sdhci.c @@ -385,6 +385,9 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) BUG_ON(data->blksz > host->mmc->max_blk_size); BUG_ON(data->blocks > 65535); + host->data = data; + host->data_early = 0; + /* timeout in us */ target_timeout = data->timeout_ns / 1000 + data->timeout_clks / host->clock; @@ -443,11 +446,11 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host, { u16 mode; - WARN_ON(host->data); - if (data == NULL) return; + WARN_ON(!host->data); + mode = SDHCI_TRNS_BLK_CNT_EN; if (data->blocks > 1) mode |= SDHCI_TRNS_MULTI; @@ -600,9 +603,10 @@ static void sdhci_finish_command(struct sdhci_host *host) host->cmd->error = MMC_ERR_NONE; - if (host->cmd->data) - host->data = host->cmd->data; - else + if (host->data && host->data_early) + sdhci_finish_data(host); + + if (!host->cmd->data) tasklet_schedule(&host->finish_tasklet); host->cmd = NULL; @@ -991,8 +995,18 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) writel(readl(host->ioaddr + SDHCI_DMA_ADDRESS), host->ioaddr + SDHCI_DMA_ADDRESS); - if (intmask & SDHCI_INT_DATA_END) - sdhci_finish_data(host); + if (intmask & SDHCI_INT_DATA_END) { + if (host->cmd) { + /* + * Data managed to finish before the + * command completed. Make sure we do + * things in the proper order. + */ + host->data_early = 1; + } else { + sdhci_finish_data(host); + } + } } } diff --git a/trunk/drivers/mmc/host/sdhci.h b/trunk/drivers/mmc/host/sdhci.h index d157776c1149..e28987d6d2eb 100644 --- a/trunk/drivers/mmc/host/sdhci.h +++ b/trunk/drivers/mmc/host/sdhci.h @@ -182,6 +182,7 @@ struct sdhci_host { struct mmc_request *mrq; /* Current request */ struct mmc_command *cmd; /* Current command */ struct mmc_data *data; /* Current data request */ + int data_early:1; /* Data finished before cmd */ struct scatterlist *cur_sg; /* We're working on this */ int num_sg; /* Entries left */