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;
 {
        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;
 
        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;
                        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);
+                       }
+               }
        }
 }
 
 
        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 */