Merge "mmc: core: fix disable clock scaling"

This commit is contained in:
Linux Build Service Account 2015-06-04 04:37:48 -07:00 committed by Gerrit - the friendly Code Review server
commit 8de2bd8526
7 changed files with 91 additions and 13 deletions

View file

@ -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;
}

View file

@ -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)

View file

@ -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",

View file

@ -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

View file

@ -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.
*/

View file

@ -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;

View file

@ -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 */