Loading drivers/mmc/core/core.c +7 −7 Original line number Diff line number Diff line Loading @@ -1170,6 +1170,8 @@ int mmc_set_auto_bkops(struct mmc_card *card, bool enable) mmc_update_bkops_auto_off(&card->bkops.stats); } card->ext_csd.bkops_en = bkops_en; pr_debug("%s: %s: bkops state %x\n", mmc_hostname(card->host), __func__, bkops_en); } out: return ret; Loading @@ -1189,9 +1191,7 @@ void mmc_check_bkops(struct mmc_card *card) BUG_ON(!card); if (unlikely(!mmc_card_configured_manual_bkops(card))) return; if (mmc_card_doing_bkops(card) || mmc_card_doing_auto_bkops(card)) if (mmc_card_doing_bkops(card)) return; err = mmc_read_bkops_status(card); Loading @@ -1201,12 +1201,12 @@ void mmc_check_bkops(struct mmc_card *card) return; } card->bkops.needs_check = false; mmc_update_bkops_level(&card->bkops.stats, card->ext_csd.raw_bkops_status); if (card->ext_csd.raw_bkops_status < EXT_CSD_BKOPS_LEVEL_2) return; card->bkops.needs_manual = true; card->bkops.needs_bkops = card->ext_csd.raw_bkops_status > 0; } EXPORT_SYMBOL(mmc_check_bkops); Loading Loading @@ -1237,7 +1237,7 @@ void mmc_start_manual_bkops(struct mmc_card *card) } else { mmc_card_set_doing_bkops(card); mmc_update_bkops_start(&card->bkops.stats); card->bkops.needs_manual = false; card->bkops.needs_bkops = false; } } EXPORT_SYMBOL(mmc_start_manual_bkops); Loading drivers/mmc/core/mmc.c +64 −0 Original line number Diff line number Diff line Loading @@ -2576,6 +2576,64 @@ static int mmc_resume(struct mmc_host *host) return err; } #define MAX_DEFER_SUSPEND_COUNTER 20 static bool mmc_process_bkops(struct mmc_host *host) { int err = 0; bool is_running = false; u32 status; mmc_claim_host(host); if (mmc_card_cmdq(host->card)) { BUG_ON(host->cmdq_ctx.active_reqs); err = mmc_cmdq_halt(host, true); if (err) { pr_err("%s: halt: failed: %d\n", __func__, err); goto unhalt; } } if (mmc_card_doing_bkops(host->card)) { /* check that manual bkops finished */ err = mmc_send_status(host->card, &status); if (err) { pr_err("%s: Get card status fail\n", __func__); goto unhalt; } if (R1_CURRENT_STATE(status) != R1_STATE_PRG) { mmc_card_clr_doing_bkops(host->card); goto unhalt; } } else { mmc_check_bkops(host->card); } if (host->card->bkops.needs_bkops && !mmc_card_support_auto_bkops(host->card)) mmc_start_manual_bkops(host->card); unhalt: if (mmc_card_cmdq(host->card)) { err = mmc_cmdq_halt(host, false); if (err) pr_err("%s: unhalt: failed: %d\n", __func__, err); } mmc_release_host(host); if (host->card->bkops.needs_bkops || mmc_card_doing_bkops(host->card)) { if (host->card->bkops.retry_counter++ < MAX_DEFER_SUSPEND_COUNTER) { host->card->bkops.needs_check = true; is_running = true; } else { host->card->bkops.retry_counter = 0; } } return is_running; } /* * Callback for runtime_suspend. */ Loading @@ -2587,6 +2645,12 @@ static int mmc_runtime_suspend(struct mmc_host *host) if (!(host->caps & MMC_CAP_AGGRESSIVE_PM)) return 0; if (mmc_process_bkops(host)) { pm_runtime_mark_last_busy(&host->card->dev); pr_debug("%s: defered, need bkops\n", __func__); return -EBUSY; } err = _mmc_suspend(host, true); if (err) pr_err("%s: error %d doing aggessive suspend\n", Loading drivers/mmc/host/cmdq_hci.c +3 −3 Original line number Diff line number Diff line /* Copyright (c) 2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2015-2016 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 and Loading Loading @@ -876,8 +876,8 @@ skip_cqterri: * exception once the queue is empty */ BUG_ON(!mmc->card); if (mmc_card_configured_manual_bkops(mmc->card) && !mmc_card_configured_auto_bkops(mmc->card)) if (mmc_card_configured_manual_bkops(mmc->card) || mmc_card_configured_auto_bkops(mmc->card)) mmc->card->bkops.needs_check = true; mrq->cmdq_req->resp_err = true; Loading include/linux/mmc/card.h +2 −1 Original line number Diff line number Diff line Loading @@ -324,7 +324,8 @@ struct mmc_bkops_stats { struct mmc_bkops_info { struct mmc_bkops_stats stats; bool needs_check; bool needs_manual; bool needs_bkops; u32 retry_counter; }; enum mmc_pon_type { Loading Loading
drivers/mmc/core/core.c +7 −7 Original line number Diff line number Diff line Loading @@ -1170,6 +1170,8 @@ int mmc_set_auto_bkops(struct mmc_card *card, bool enable) mmc_update_bkops_auto_off(&card->bkops.stats); } card->ext_csd.bkops_en = bkops_en; pr_debug("%s: %s: bkops state %x\n", mmc_hostname(card->host), __func__, bkops_en); } out: return ret; Loading @@ -1189,9 +1191,7 @@ void mmc_check_bkops(struct mmc_card *card) BUG_ON(!card); if (unlikely(!mmc_card_configured_manual_bkops(card))) return; if (mmc_card_doing_bkops(card) || mmc_card_doing_auto_bkops(card)) if (mmc_card_doing_bkops(card)) return; err = mmc_read_bkops_status(card); Loading @@ -1201,12 +1201,12 @@ void mmc_check_bkops(struct mmc_card *card) return; } card->bkops.needs_check = false; mmc_update_bkops_level(&card->bkops.stats, card->ext_csd.raw_bkops_status); if (card->ext_csd.raw_bkops_status < EXT_CSD_BKOPS_LEVEL_2) return; card->bkops.needs_manual = true; card->bkops.needs_bkops = card->ext_csd.raw_bkops_status > 0; } EXPORT_SYMBOL(mmc_check_bkops); Loading Loading @@ -1237,7 +1237,7 @@ void mmc_start_manual_bkops(struct mmc_card *card) } else { mmc_card_set_doing_bkops(card); mmc_update_bkops_start(&card->bkops.stats); card->bkops.needs_manual = false; card->bkops.needs_bkops = false; } } EXPORT_SYMBOL(mmc_start_manual_bkops); Loading
drivers/mmc/core/mmc.c +64 −0 Original line number Diff line number Diff line Loading @@ -2576,6 +2576,64 @@ static int mmc_resume(struct mmc_host *host) return err; } #define MAX_DEFER_SUSPEND_COUNTER 20 static bool mmc_process_bkops(struct mmc_host *host) { int err = 0; bool is_running = false; u32 status; mmc_claim_host(host); if (mmc_card_cmdq(host->card)) { BUG_ON(host->cmdq_ctx.active_reqs); err = mmc_cmdq_halt(host, true); if (err) { pr_err("%s: halt: failed: %d\n", __func__, err); goto unhalt; } } if (mmc_card_doing_bkops(host->card)) { /* check that manual bkops finished */ err = mmc_send_status(host->card, &status); if (err) { pr_err("%s: Get card status fail\n", __func__); goto unhalt; } if (R1_CURRENT_STATE(status) != R1_STATE_PRG) { mmc_card_clr_doing_bkops(host->card); goto unhalt; } } else { mmc_check_bkops(host->card); } if (host->card->bkops.needs_bkops && !mmc_card_support_auto_bkops(host->card)) mmc_start_manual_bkops(host->card); unhalt: if (mmc_card_cmdq(host->card)) { err = mmc_cmdq_halt(host, false); if (err) pr_err("%s: unhalt: failed: %d\n", __func__, err); } mmc_release_host(host); if (host->card->bkops.needs_bkops || mmc_card_doing_bkops(host->card)) { if (host->card->bkops.retry_counter++ < MAX_DEFER_SUSPEND_COUNTER) { host->card->bkops.needs_check = true; is_running = true; } else { host->card->bkops.retry_counter = 0; } } return is_running; } /* * Callback for runtime_suspend. */ Loading @@ -2587,6 +2645,12 @@ static int mmc_runtime_suspend(struct mmc_host *host) if (!(host->caps & MMC_CAP_AGGRESSIVE_PM)) return 0; if (mmc_process_bkops(host)) { pm_runtime_mark_last_busy(&host->card->dev); pr_debug("%s: defered, need bkops\n", __func__); return -EBUSY; } err = _mmc_suspend(host, true); if (err) pr_err("%s: error %d doing aggessive suspend\n", Loading
drivers/mmc/host/cmdq_hci.c +3 −3 Original line number Diff line number Diff line /* Copyright (c) 2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2015-2016 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 and Loading Loading @@ -876,8 +876,8 @@ skip_cqterri: * exception once the queue is empty */ BUG_ON(!mmc->card); if (mmc_card_configured_manual_bkops(mmc->card) && !mmc_card_configured_auto_bkops(mmc->card)) if (mmc_card_configured_manual_bkops(mmc->card) || mmc_card_configured_auto_bkops(mmc->card)) mmc->card->bkops.needs_check = true; mrq->cmdq_req->resp_err = true; Loading
include/linux/mmc/card.h +2 −1 Original line number Diff line number Diff line Loading @@ -324,7 +324,8 @@ struct mmc_bkops_stats { struct mmc_bkops_info { struct mmc_bkops_stats stats; bool needs_check; bool needs_manual; bool needs_bkops; u32 retry_counter; }; enum mmc_pon_type { Loading