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

Commit b680bce5 authored by Lee Susman's avatar Lee Susman Committed by Konstantin Dorfman
Browse files

mmc: host: disable only sdhci irqs in sdhci_request



When using the _irqsave variant of spin_lock, irqs are disabled. In the
case of sdhci_request, this can result in relatively long periods of time
in which the irqs are disabled (up to at least 170us observed).
Since in this flow not all interrupts need to be disabled,
we use regular spin_locks here, and disable only sdhci-specific interrupts.
For this, introduce a new sdhci_ops function for enabling/disabling the
platform-specific power irqs.

CRs-Fixed: 709331
Change-Id: Ia9fb0498aab3053b393d677bae097fcd846d8180
Signed-off-by: default avatarLee Susman <lsusman@codeaurora.org>
Signed-off-by: default avatarKonstantin Dorfman <kdorfman@codeaurora.org>
parent 2f0184f7
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -2432,7 +2432,16 @@ out:
	return rc;
}

static void sdhci_msm_cfg_power_irq(struct sdhci_host *host, bool enable)
{
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
	struct sdhci_msm_host *msm_host = pltfm_host->priv;

	if (enable)
		enable_irq(msm_host->pwr_irq);
	else
		disable_irq(msm_host->pwr_irq);
}

static int sdhci_msm_prepare_clocks(struct sdhci_host *host, bool enable)
{
@@ -2873,6 +2882,7 @@ static struct sdhci_ops sdhci_msm_ops = {
	.dump_vendor_regs = sdhci_msm_dump_vendor_regs,
	.config_auto_tuning_cmd = sdhci_msm_config_auto_tuning_cmd,
	.enable_controller_clock = sdhci_msm_enable_controller_clock,
	.cfg_power_irq = sdhci_msm_cfg_power_irq,
};

static int sdhci_msm_cfg_mpm_pin_wakeup(struct sdhci_host *host, unsigned mode)
+37 −20
Original line number Diff line number Diff line
@@ -1630,11 +1630,39 @@ static int sdhci_get_tuning_cmd(struct sdhci_host *host)
		return MMC_SEND_TUNING_BLOCK;
}

static void sdhci_cfg_irq(struct sdhci_host *host, bool enable, bool sync)
{
	if (enable && !host->irq_enabled) {
		enable_irq(host->irq);
		host->irq_enabled = true;
	} else if (!enable && host->irq_enabled) {
		if (sync)
			disable_irq(host->irq);
		else
			disable_irq_nosync(host->irq);
		host->irq_enabled = false;
	}
}

#define SDHCI_SPIN_LOCK(host, enable)					\
	do {								\
		if (enable) {						\
			sdhci_cfg_irq(host, !enable, true);		\
			if (host->ops->cfg_power_irq)			\
				host->ops->cfg_power_irq(host, !enable);\
			spin_lock(&host->lock);				\
		} else {						\
			spin_unlock(&host->lock);			\
			sdhci_cfg_irq(host, !enable, true);		\
			if (host->ops->cfg_power_irq)			\
				host->ops->cfg_power_irq(host, !enable);\
		}							\
	} while (0)

static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
{
	struct sdhci_host *host;
	int present;
	unsigned long flags;
	u32 tuning_opcode;

	host = mmc_priv(mmc);
@@ -1668,7 +1696,7 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
					SDHCI_CARD_PRESENT;
	}

	spin_lock_irqsave(&host->lock, flags);
	SDHCI_SPIN_LOCK(host, true);

	WARN_ON(host->mrq != NULL);

@@ -1714,9 +1742,9 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
					MMC_SEND_TUNING_BLOCK;
				host->mrq = NULL;
				host->flags &= ~SDHCI_NEEDS_RETUNING;
				spin_unlock_irqrestore(&host->lock, flags);
				SDHCI_SPIN_LOCK(host, false);
				sdhci_execute_tuning(mmc, tuning_opcode);
				spin_lock_irqsave(&host->lock, flags);
				SDHCI_SPIN_LOCK(host, true);

				/* Restore original mmc_request structure */
				host->mrq = mrq;
@@ -1739,7 +1767,7 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
	}

	mmiowb();
	spin_unlock_irqrestore(&host->lock, flags);
	SDHCI_SPIN_LOCK(host, false);
}

static void sdhci_cfg_async_intr(struct sdhci_host *host, bool enable)
@@ -1758,17 +1786,6 @@ static void sdhci_cfg_async_intr(struct sdhci_host *host, bool enable)
			     SDHCI_HOST_CONTROL2);
}

static void sdhci_cfg_irq(struct sdhci_host *host, bool enable)
{
	if (enable && !host->irq_enabled) {
		enable_irq(host->irq);
		host->irq_enabled = true;
	} else if (!enable && host->irq_enabled) {
		disable_irq_nosync(host->irq);
		host->irq_enabled = false;
	}
}

static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
{
	unsigned long flags;
@@ -1786,7 +1803,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)

	spin_lock_irqsave(&host->lock, flags);
	/* lock is being released intermittently below, hence disable irq */
	sdhci_cfg_irq(host, false);
	sdhci_cfg_irq(host, false, false);
	spin_unlock_irqrestore(&host->lock, flags);
	if (ios->clock) {
		sdhci_set_clock(host, ios->clock);
@@ -1829,7 +1846,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
	}
	spin_lock_irqsave(&host->lock, flags);
	if (!host->clock) {
		sdhci_cfg_irq(host, true);
		sdhci_cfg_irq(host, true, false);
		spin_unlock_irqrestore(&host->lock, flags);
		mutex_unlock(&host->ios_mutex);
		return;
@@ -2010,7 +2027,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
		sdhci_set_clock(host, ios->clock);
	}
	spin_lock_irqsave(&host->lock, flags);
	sdhci_cfg_irq(host, true);
	sdhci_cfg_irq(host, true, false);
	spin_unlock_irqrestore(&host->lock, flags);
	mmiowb();
	mutex_unlock(&host->ios_mutex);
@@ -2997,7 +3014,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
	if (!host->clock && host->mmc->card &&
	    mmc_card_sdio(host->mmc->card)) {
		/* SDIO async. interrupt is level-sensitive */
		sdhci_cfg_irq(host, false);
		sdhci_cfg_irq(host, false, false);
		pr_debug("%s: got async-irq: clocks: %d gated: %d host-irq[en:1/dis:0]: %d\n",
			mmc_hostname(host->mmc), host->clock,
			host->mmc->clk_gated, host->irq_enabled);
+1 −0
Original line number Diff line number Diff line
@@ -321,6 +321,7 @@ struct sdhci_ops {
					  bool enable,
					  u32 type);
	int	(*enable_controller_clock)(struct sdhci_host *host);
	void	(*cfg_power_irq)(struct sdhci_host *host, bool enable);
};

#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS