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

Commit 586071f6 authored by Gilad Broner's avatar Gilad Broner
Browse files

mmc: sdhci-msm: add PM QoS legacy voting



Add PM QoS voting mechanism to sdhci-msm driver for legacy
eMMC.
Two types of voting schemes are supported:
1) Vote for HW IRQ
2) Vote for a cpu group according to the request's designated cpu
Using PM QoS voting should benefit performance.

Change-Id: I5d2b71fc4eabfa5060f343634fbc7363f2ee1344
Signed-off-by: default avatarKonstantin Dorfman <kdorfman@codeaurora.org>
Signed-off-by: default avatarGilad Broner <gbroner@codeaurora.org>
parent e34ad72e
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -473,6 +473,10 @@ cur_sg_alloc_failed:
success:
	sema_init(&mq->thread_sem, 1);

	/* hook for pm qos legacy init */
	if (card->host->ops->init)
		card->host->ops->init(card->host);

	mq->thread = kthread_run(mmc_queue_thread, mq, "mmcqd/%d%s",
		host->index, subname ? subname : "");

+63 −3
Original line number Diff line number Diff line
@@ -3291,7 +3291,7 @@ static void sdhci_msm_pm_qos_cpu_unvote_work(struct work_struct *work)
	pm_qos_update_request(&group->req, group->latency);
}

void sdhci_msm_pm_qos_cpu_unvote(struct sdhci_host *host, int cpu, bool async)
bool sdhci_msm_pm_qos_cpu_unvote(struct sdhci_host *host, int cpu, bool async)
{
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
	struct sdhci_msm_host *msm_host = pltfm_host->priv;
@@ -3299,16 +3299,17 @@ void sdhci_msm_pm_qos_cpu_unvote(struct sdhci_host *host, int cpu, bool async)

	if (!msm_host->pm_qos_group_enable || group < 0 ||
		atomic_dec_return(&msm_host->pm_qos[group].counter))
		return;
		return false;

	if (async) {
		schedule_work(&msm_host->pm_qos[group].unvote_work);
		return;
		return true;
	}

	msm_host->pm_qos[group].latency = PM_QOS_DEFAULT_VALUE;
	pm_qos_update_request(&msm_host->pm_qos[group].req,
				msm_host->pm_qos[group].latency);
	return true;
}

void sdhci_msm_pm_qos_cpu_init(struct sdhci_host *host,
@@ -3346,9 +3347,65 @@ void sdhci_msm_pm_qos_cpu_init(struct sdhci_host *host,
			group->latency,
			&latency[i].latency[SDHCI_PERFORMANCE_MODE]);
	}
	msm_host->pm_qos_prev_cpu = -1;
	msm_host->pm_qos_group_enable = true;
}

static void sdhci_msm_pre_req(struct sdhci_host *host,
		struct mmc_request *mmc_req)
{
	int cpu;
	int group;
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
	struct sdhci_msm_host *msm_host = pltfm_host->priv;
	int prev_group = sdhci_msm_get_cpu_group(msm_host,
			msm_host->pm_qos_prev_cpu);

	sdhci_msm_pm_qos_irq_vote(host);

	cpu = get_cpu();
	put_cpu();
	group = sdhci_msm_get_cpu_group(msm_host, cpu);
	if (group < 0)
		return;

	if (group != prev_group && prev_group >= 0) {
		sdhci_msm_pm_qos_cpu_unvote(host,
				msm_host->pm_qos_prev_cpu, false);
		prev_group = -1; /* make sure to vote for new group */
	}

	if (prev_group < 0) {
		sdhci_msm_pm_qos_cpu_vote(host,
				msm_host->pdata->pm_qos_data.latency, cpu);
		msm_host->pm_qos_prev_cpu = cpu;
	}
}

static void sdhci_msm_post_req(struct sdhci_host *host,
				struct mmc_request *mmc_req)
{
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
	struct sdhci_msm_host *msm_host = pltfm_host->priv;

	sdhci_msm_pm_qos_irq_unvote(host, false);

	if (sdhci_msm_pm_qos_cpu_unvote(host, msm_host->pm_qos_prev_cpu, false))
			msm_host->pm_qos_prev_cpu = -1;
}

static void sdhci_msm_init(struct sdhci_host *host)
{
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
	struct sdhci_msm_host *msm_host = pltfm_host->priv;

	sdhci_msm_pm_qos_irq_init(host);

	if (msm_host->pdata->pm_qos_data.legacy_valid)
		sdhci_msm_pm_qos_cpu_init(host,
				msm_host->pdata->pm_qos_data.latency);
}

static struct sdhci_ops sdhci_msm_ops = {
	.crypto_engine_cfg = sdhci_msm_ice_cfg,
	.crypto_engine_reset = sdhci_msm_ice_reset,
@@ -3371,6 +3428,9 @@ static struct sdhci_ops sdhci_msm_ops = {
	.detect = sdhci_msm_detect,
	.notify_load = sdhci_msm_notify_load,
	.reset_workaround = sdhci_msm_reset_workaround,
	.init = sdhci_msm_init,
	.pre_req = sdhci_msm_pre_req,
	.post_req = sdhci_msm_post_req,
};

static void sdhci_set_default_hw_caps(struct sdhci_msm_host *msm_host,
+2 −2
Original line number Diff line number Diff line
@@ -203,7 +203,7 @@ struct sdhci_msm_host {
	struct sdhci_msm_ice_data ice;
	u32 ice_clk_rate;
	struct sdhci_msm_pm_qos_group *pm_qos;
	int pm_qos_prev_group;
	int pm_qos_prev_cpu;
	bool pm_qos_group_enable;
	struct sdhci_msm_pm_qos_irq pm_qos_irq;
};
@@ -218,7 +218,7 @@ void sdhci_msm_pm_qos_cpu_init(struct sdhci_host *host,
		struct sdhci_msm_pm_qos_latency *latency);
void sdhci_msm_pm_qos_cpu_vote(struct sdhci_host *host,
		struct sdhci_msm_pm_qos_latency *latency, int cpu);
void sdhci_msm_pm_qos_cpu_unvote(struct sdhci_host *host, int cpu, bool async);
bool sdhci_msm_pm_qos_cpu_unvote(struct sdhci_host *host, int cpu, bool async);


#endif /* __SDHCI_MSM_H__ */
+13 −0
Original line number Diff line number Diff line
@@ -1592,6 +1592,8 @@ static void sdhci_pre_req(struct mmc_host *mmc, struct mmc_request *mrq,
	if (host->flags & SDHCI_REQ_USE_DMA)
		if (sdhci_pre_dma_transfer(host, mrq->data, &host->next_data) < 0)
			mrq->data->host_cookie = 0;
	if (host->ops->pre_req)
		host->ops->pre_req(host, mrq);
}

static void sdhci_post_req(struct mmc_host *mmc, struct mmc_request *mrq,
@@ -1606,6 +1608,8 @@ static void sdhci_post_req(struct mmc_host *mmc, struct mmc_request *mrq,
			     DMA_TO_DEVICE : DMA_FROM_DEVICE);
		data->host_cookie = 0;
	}
	if (host->ops->post_req)
		host->ops->post_req(host, mrq);
}

static bool sdhci_check_state(struct sdhci_host *host)
@@ -2595,8 +2599,17 @@ static void sdhci_detect(struct mmc_host *mmc, bool detected)
	if (host->ops->detect)
		host->ops->detect(host, detected);
}
static int sdhci_late_init(struct mmc_host *mmc)
{
	struct sdhci_host *host = mmc_priv(mmc);

	if (host->ops->init)
		host->ops->init(host);

	return 0;
}
static const struct mmc_host_ops sdhci_ops = {
	.init           = sdhci_late_init,
	.pre_req	= sdhci_pre_req,
	.post_req	= sdhci_post_req,
	.request	= sdhci_request,
+3 −0
Original line number Diff line number Diff line
@@ -333,6 +333,9 @@ struct sdhci_ops {
	void	(*detect)(struct sdhci_host *host, bool detected);
	int	(*notify_load)(struct sdhci_host *host, enum mmc_load state);
	void	(*reset_workaround)(struct sdhci_host *host, u32 enable);
	void	(*init)(struct sdhci_host *host);
	void	(*pre_req)(struct sdhci_host *host, struct mmc_request *req);
	void	(*post_req)(struct sdhci_host *host, struct mmc_request *req);
};

#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
Loading