Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e538fbe8 authored by Pierre Ossman's avatar Pierre Ossman
Browse files

sdhci: handle data interrupts during command



It is fully legal for a controller to start issuing data related
interrupts before it has signalled that the command has completed.
Make sure the driver actually can handle this.

Signed-off-by: default avatarPierre Ossman <drzeus@drzeus.cx>
parent 03f8590d
Loading
Loading
Loading
Loading
+21 −7
Original line number Diff line number Diff line
@@ -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,10 +995,20 @@ 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)
		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);
			}
		}
	}
}

static irqreturn_t sdhci_irq(int irq, void *dev_id)
{
+1 −0
Original line number Diff line number Diff line
@@ -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 */