mirror of
https://github.com/team-infusion-developers/android_kernel_samsung_msm8976.git
synced 2024-09-21 20:04:01 +00:00
Merge "mmc: core: fix disable clock scaling"
This commit is contained in:
commit
8de2bd8526
7 changed files with 91 additions and 13 deletions
|
@ -1492,6 +1492,7 @@ out:
|
|||
if (test_and_clear_bit(0, &ctx_info->req_starved))
|
||||
blk_run_queue(mq->queue);
|
||||
mmc_release_host(host);
|
||||
mmc_rpm_release(host, &card->dev);
|
||||
return err ? 1 : 0;
|
||||
}
|
||||
|
||||
|
@ -1611,6 +1612,7 @@ out:
|
|||
if (test_and_clear_bit(0, &ctx_info->req_starved))
|
||||
blk_run_queue(mq->queue);
|
||||
mmc_release_host(host);
|
||||
mmc_rpm_release(host, &card->dev);
|
||||
return err ? 1 : 0;
|
||||
}
|
||||
|
||||
|
@ -3002,6 +3004,7 @@ static void mmc_blk_cmdq_shutdown(struct mmc_queue *mq)
|
|||
return;
|
||||
}
|
||||
|
||||
mmc_rpm_hold(host, &card->dev);
|
||||
mmc_claim_host(card->host);
|
||||
/* disable CQ mode in card */
|
||||
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
||||
|
@ -3016,6 +3019,7 @@ static void mmc_blk_cmdq_shutdown(struct mmc_queue *mq)
|
|||
}
|
||||
out:
|
||||
mmc_release_host(card->host);
|
||||
mmc_rpm_release(host, &card->dev);
|
||||
}
|
||||
|
||||
static enum blk_eh_timer_return mmc_blk_cmdq_req_timed_out(struct request *req)
|
||||
|
@ -3050,6 +3054,7 @@ static void mmc_blk_cmdq_err(struct mmc_queue *mq)
|
|||
struct mmc_card *card = mq->card;
|
||||
struct mmc_cmdq_context_info *ctx_info = &host->cmdq_ctx;
|
||||
|
||||
mmc_rpm_hold(host, &card->dev);
|
||||
err = mmc_cmdq_halt(host, true);
|
||||
if (err) {
|
||||
pr_err("halt: failed: %d\n", err);
|
||||
|
@ -3109,6 +3114,8 @@ unhalt:
|
|||
mmc_cmdq_halt(host, false);
|
||||
|
||||
out:
|
||||
mmc_rpm_release(host, &card->dev);
|
||||
|
||||
if (test_and_clear_bit(0, &ctx_info->req_starved))
|
||||
blk_run_queue(mrq->req->q);
|
||||
}
|
||||
|
@ -3175,6 +3182,7 @@ out:
|
|||
test_and_clear_bit(0, &ctx_info->req_starved))
|
||||
blk_run_queue(mq->queue);
|
||||
mmc_release_host(host);
|
||||
mmc_rpm_release(host, &host->card->dev);
|
||||
|
||||
if (!ctx_info->active_reqs)
|
||||
wake_up_interruptible(&host->cmdq_ctx.queue_empty_wq);
|
||||
|
@ -3465,6 +3473,7 @@ static int mmc_blk_cmdq_issue_rq(struct mmc_queue *mq, struct request *req)
|
|||
struct mmc_card *card = md->queue.card;
|
||||
unsigned int cmd_flags = req ? req->cmd_flags : 0;
|
||||
|
||||
mmc_rpm_hold(card->host, &card->dev);
|
||||
mmc_claim_host(card->host);
|
||||
ret = mmc_blk_cmdq_part_switch(card, md);
|
||||
if (ret) {
|
||||
|
@ -3472,6 +3481,7 @@ static int mmc_blk_cmdq_issue_rq(struct mmc_queue *mq, struct request *req)
|
|||
md->disk->disk_name, __func__, ret);
|
||||
blk_end_request_all(req, ret);
|
||||
mmc_release_host(card->host);
|
||||
mmc_rpm_release(card->host, &card->dev);
|
||||
goto switch_failure;
|
||||
}
|
||||
|
||||
|
|
|
@ -58,16 +58,22 @@ static inline bool mmc_cmdq_should_pull_reqs(struct mmc_host *host,
|
|||
struct request *req)
|
||||
|
||||
{
|
||||
if (((req->cmd_flags & (REQ_FLUSH | REQ_DISCARD)) &&
|
||||
test_bit(CMDQ_STATE_DCMD_ACTIVE, &ctx->curr_state)) ||
|
||||
(!host->card->part_curr && mmc_host_halt(host)) ||
|
||||
test_bit(CMDQ_STATE_ERR, &ctx->curr_state)) {
|
||||
pr_debug("%s: %s: skip pulling reqs: state: %lu\n",
|
||||
mmc_hostname(host), __func__, ctx->curr_state);
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
bool ret = true;
|
||||
|
||||
if ((req->cmd_flags & (REQ_FLUSH | REQ_DISCARD)) &&
|
||||
test_bit(CMDQ_STATE_DCMD_ACTIVE, &ctx->curr_state))
|
||||
ret = false;
|
||||
else if (!host->card->part_curr &&
|
||||
mmc_host_halt(host) && !mmc_card_suspended(host->card))
|
||||
ret = false;
|
||||
else if (test_bit(CMDQ_STATE_ERR, &ctx->curr_state))
|
||||
ret = false;
|
||||
|
||||
if (!ret)
|
||||
pr_debug("%s: %s: skip pulling reqs: state: %lu, cmd_flags: 0x%x\n",
|
||||
mmc_hostname(host), __func__,
|
||||
ctx->curr_state, req->cmd_flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mmc_cmdq_thread(void *d)
|
||||
|
|
|
@ -3580,7 +3580,10 @@ EXPORT_SYMBOL(mmc_clk_scaling);
|
|||
*/
|
||||
void mmc_disable_clk_scaling(struct mmc_host *host)
|
||||
{
|
||||
cancel_delayed_work_sync(&host->clk_scaling.work);
|
||||
if (host->clk_scaling.enable &&
|
||||
host->card && !mmc_card_cmdq(host->card))
|
||||
cancel_delayed_work_sync(&host->clk_scaling.work);
|
||||
|
||||
if (host->ops->notify_load)
|
||||
host->ops->notify_load(host, MMC_LOAD_LOW);
|
||||
host->clk_scaling.enable = false;
|
||||
|
@ -4327,7 +4330,7 @@ void mmc_rpm_release(struct mmc_host *host, struct device *dev)
|
|||
if (!mmc_use_core_runtime_pm(host))
|
||||
return;
|
||||
|
||||
ret = pm_runtime_put_sync(dev);
|
||||
ret = pm_runtime_put(dev);
|
||||
if ((ret < 0) &&
|
||||
(dev->power.runtime_error || (dev->power.disable_depth > 0))) {
|
||||
pr_err("%s: %s: %s: pm_runtime_put_sync: err: %d\n",
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* Copyright (C) 2003 Russell King, All Rights Reserved.
|
||||
* Copyright (C) 2007-2008 Pierre Ossman
|
||||
* Copyright (C) 2010 Linus Walleij
|
||||
* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
|
@ -28,6 +28,7 @@
|
|||
#include <linux/mmc/host.h>
|
||||
#include <linux/mmc/card.h>
|
||||
#include <linux/mmc/slot-gpio.h>
|
||||
#include <trace/events/mmc.h>
|
||||
|
||||
#include "core.h"
|
||||
#include "host.h"
|
||||
|
@ -47,10 +48,24 @@ static int mmc_host_runtime_suspend(struct device *dev)
|
|||
{
|
||||
struct mmc_host *host = cls_dev_to_mmc_host(dev);
|
||||
int ret = 0;
|
||||
ktime_t start = ktime_get();
|
||||
|
||||
if (!mmc_use_core_runtime_pm(host))
|
||||
return 0;
|
||||
|
||||
if (host->card && mmc_card_cmdq(host->card)) {
|
||||
BUG_ON(host->cmdq_ctx.active_reqs);
|
||||
|
||||
mmc_card_set_suspended(host->card);
|
||||
ret = mmc_cmdq_halt(host, true);
|
||||
if (ret) {
|
||||
mmc_card_clr_suspended(host->card);
|
||||
pr_err("%s: halt: failed: %d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
host->cmdq_ops->disable(host, true);
|
||||
}
|
||||
|
||||
ret = mmc_suspend_host(host);
|
||||
if (ret < 0 && ret != -ENOMEDIUM)
|
||||
pr_err("%s: %s: suspend host failed: %d\n", mmc_hostname(host),
|
||||
|
@ -75,6 +90,8 @@ static int mmc_host_runtime_suspend(struct device *dev)
|
|||
if (ret == -ENOMEDIUM)
|
||||
ret = 0;
|
||||
|
||||
trace_mmc_host_runtime_suspend(mmc_hostname(host), ret,
|
||||
ktime_to_us(ktime_sub(ktime_get(), start)));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -82,6 +99,7 @@ static int mmc_host_runtime_resume(struct device *dev)
|
|||
{
|
||||
struct mmc_host *host = cls_dev_to_mmc_host(dev);
|
||||
int ret = 0;
|
||||
ktime_t start = ktime_get();
|
||||
|
||||
if (!mmc_use_core_runtime_pm(host))
|
||||
return 0;
|
||||
|
@ -94,6 +112,15 @@ static int mmc_host_runtime_resume(struct device *dev)
|
|||
BUG_ON(1);
|
||||
}
|
||||
|
||||
if (host->card && !ret && mmc_card_cmdq(host->card)) {
|
||||
ret = mmc_cmdq_halt(host, false);
|
||||
if (ret)
|
||||
pr_err("%s: un-halt: failed: %d\n", __func__, ret);
|
||||
else
|
||||
mmc_card_clr_suspended(host->card);
|
||||
}
|
||||
trace_mmc_host_runtime_resume(mmc_hostname(host), ret,
|
||||
ktime_to_us(ktime_sub(ktime_get(), start)));
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
@ -115,6 +142,18 @@ static int mmc_host_suspend(struct device *dev)
|
|||
host->dev_status = DEV_SUSPENDING;
|
||||
spin_unlock_irqrestore(&host->clk_lock, flags);
|
||||
if (!pm_runtime_suspended(dev)) {
|
||||
if (host->card && mmc_card_cmdq(host->card)) {
|
||||
BUG_ON(host->cmdq_ctx.active_reqs);
|
||||
|
||||
mmc_card_set_suspended(host->card);
|
||||
ret = mmc_cmdq_halt(host, true);
|
||||
if (ret) {
|
||||
mmc_card_clr_suspended(host->card);
|
||||
pr_err("%s: halt: failed: %d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
host->cmdq_ops->disable(host, true);
|
||||
}
|
||||
ret = mmc_suspend_host(host);
|
||||
if (ret < 0)
|
||||
pr_err("%s: %s: failed: ret: %d\n", mmc_hostname(host),
|
||||
|
@ -154,6 +193,13 @@ static int mmc_host_resume(struct device *dev)
|
|||
__func__, ret);
|
||||
}
|
||||
host->dev_status = DEV_RESUMED;
|
||||
if (host->card && !ret && mmc_card_cmdq(host->card)) {
|
||||
ret = mmc_cmdq_halt(host, false);
|
||||
if (ret)
|
||||
pr_err("%s: un-halt: failed: %d\n", __func__, ret);
|
||||
else
|
||||
mmc_card_clr_suspended(host->card);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -342,6 +342,7 @@ struct mmc_card {
|
|||
#define MMC_STATE_DOING_BKOPS (1<<10) /* card is doing BKOPS */
|
||||
#define MMC_STATE_NEED_BKOPS (1<<11) /* card needs to do BKOPS */
|
||||
#define MMC_STATE_CMDQ (1<<12) /* card is in cmd queue mode */
|
||||
#define MMC_STATE_SUSPENDED (1<<13) /* card is suspended */
|
||||
unsigned int quirks; /* card quirks */
|
||||
#define MMC_QUIRK_LENIENT_FN0 (1<<0) /* allow SDIO FN0 writes outside of the VS CCCR range */
|
||||
#define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1) /* use func->cur_blksize */
|
||||
|
@ -566,6 +567,7 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)
|
|||
#define mmc_card_doing_bkops(c) ((c)->state & MMC_STATE_DOING_BKOPS)
|
||||
#define mmc_card_need_bkops(c) ((c)->state & MMC_STATE_NEED_BKOPS)
|
||||
#define mmc_card_cmdq(c) ((c)->state & MMC_STATE_CMDQ)
|
||||
#define mmc_card_suspended(c) ((c)->state & MMC_STATE_SUSPENDED)
|
||||
|
||||
#define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT)
|
||||
#define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
|
||||
|
@ -588,6 +590,8 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)
|
|||
#define mmc_card_clr_need_bkops(c) ((c)->state &= ~MMC_STATE_NEED_BKOPS)
|
||||
#define mmc_card_set_cmdq(c) ((c)->state |= MMC_STATE_CMDQ)
|
||||
#define mmc_card_clr_cmdq(c) ((c)->state &= ~MMC_STATE_CMDQ)
|
||||
#define mmc_card_set_suspended(c) ((c)->state |= MMC_STATE_SUSPENDED)
|
||||
#define mmc_card_clr_suspended(c) ((c)->state &= ~MMC_STATE_SUSPENDED)
|
||||
/*
|
||||
* Quirk add/remove for MMC products.
|
||||
*/
|
||||
|
|
|
@ -248,6 +248,7 @@ struct mmc_cmdq_context_info {
|
|||
#define CMDQ_STATE_ERR 0
|
||||
#define CMDQ_STATE_DCMD_ACTIVE 1
|
||||
#define CMDQ_STATE_HALT 2
|
||||
#define CMDQ_STATE_RPM_ACTIVE 3
|
||||
/* no free tag available */
|
||||
unsigned long req_starved;
|
||||
wait_queue_head_t queue_empty_wq;
|
||||
|
|
|
@ -209,6 +209,14 @@ DEFINE_EVENT(mmc_pm_template, mmc_resume_host,
|
|||
TP_PROTO(const char *dev_name, int err, s64 usecs),
|
||||
TP_ARGS(dev_name, err, usecs));
|
||||
|
||||
DEFINE_EVENT(mmc_pm_template, mmc_host_runtime_suspend,
|
||||
TP_PROTO(const char *dev_name, int err, s64 usecs),
|
||||
TP_ARGS(dev_name, err, usecs));
|
||||
|
||||
DEFINE_EVENT(mmc_pm_template, mmc_host_runtime_resume,
|
||||
TP_PROTO(const char *dev_name, int err, s64 usecs),
|
||||
TP_ARGS(dev_name, err, usecs));
|
||||
|
||||
#endif /* if !defined(_TRACE_MMC_H) || defined(TRACE_HEADER_MULTI_READ) */
|
||||
|
||||
/* This part must be outside protection */
|
||||
|
|
Loading…
Reference in a new issue