|
@@ -1266,9 +1266,31 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask)
|
|
SDHCI_INT_INDEX))
|
|
SDHCI_INT_INDEX))
|
|
host->cmd->error = -EILSEQ;
|
|
host->cmd->error = -EILSEQ;
|
|
|
|
|
|
- if (host->cmd->error)
|
|
|
|
|
|
+ if (host->cmd->error) {
|
|
tasklet_schedule(&host->finish_tasklet);
|
|
tasklet_schedule(&host->finish_tasklet);
|
|
- else if (intmask & SDHCI_INT_RESPONSE)
|
|
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * The host can send and interrupt when the busy state has
|
|
|
|
+ * ended, allowing us to wait without wasting CPU cycles.
|
|
|
|
+ * Unfortunately this is overloaded on the "data complete"
|
|
|
|
+ * interrupt, so we need to take some care when handling
|
|
|
|
+ * it.
|
|
|
|
+ *
|
|
|
|
+ * Note: The 1.0 specification is a bit ambiguous about this
|
|
|
|
+ * feature so there might be some problems with older
|
|
|
|
+ * controllers.
|
|
|
|
+ */
|
|
|
|
+ if (host->cmd->flags & MMC_RSP_BUSY) {
|
|
|
|
+ if (host->cmd->data)
|
|
|
|
+ DBG("Cannot wait for busy signal when also "
|
|
|
|
+ "doing a data transfer");
|
|
|
|
+ else
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (intmask & SDHCI_INT_RESPONSE)
|
|
sdhci_finish_command(host);
|
|
sdhci_finish_command(host);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1278,11 +1300,16 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
|
|
|
|
|
|
if (!host->data) {
|
|
if (!host->data) {
|
|
/*
|
|
/*
|
|
- * A data end interrupt is sent together with the response
|
|
|
|
- * for the stop command.
|
|
|
|
|
|
+ * The "data complete" interrupt is also used to
|
|
|
|
+ * indicate that a busy state has ended. See comment
|
|
|
|
+ * above in sdhci_cmd_irq().
|
|
*/
|
|
*/
|
|
- if (intmask & SDHCI_INT_DATA_END)
|
|
|
|
- return;
|
|
|
|
|
|
+ if (host->cmd && (host->cmd->flags & MMC_RSP_BUSY)) {
|
|
|
|
+ if (intmask & SDHCI_INT_DATA_END) {
|
|
|
|
+ sdhci_finish_command(host);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
|
|
printk(KERN_ERR "%s: Got data interrupt 0x%08x even "
|
|
printk(KERN_ERR "%s: Got data interrupt 0x%08x even "
|
|
"though no data operation was in progress.\n",
|
|
"though no data operation was in progress.\n",
|