Loading arch/arm64/configs/vendor/sdmsteppe_defconfig +1 −0 Original line number Diff line number Diff line Loading @@ -714,6 +714,7 @@ CONFIG_DEBUG_CREDENTIALS=y CONFIG_RCU_TORTURE_TEST=m CONFIG_FAULT_INJECTION=y CONFIG_FAIL_PAGE_ALLOC=y CONFIG_FAIL_MMC_REQUEST=y CONFIG_UFS_FAULT_INJECTION=y CONFIG_FAULT_INJECTION_DEBUG_FS=y CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y Loading drivers/mmc/core/block.c +45 −24 Original line number Diff line number Diff line Loading @@ -2429,17 +2429,17 @@ static struct mmc_cmdq_req *mmc_blk_cmdq_prep_discard_req(struct mmc_queue *mq, struct mmc_cmdq_req *cmdq_req; struct mmc_queue_req *active_mqrq; BUG_ON(req->tag > card->ext_csd.cmdq_depth); BUG_ON(test_and_set_bit(req->tag, &host->cmdq_ctx.active_reqs)); set_bit(CMDQ_STATE_DCMD_ACTIVE, &ctx_info->curr_state); active_mqrq = req_to_mmc_queue_req(req); cmdq_req = mmc_cmdq_prep_dcmd(active_mqrq, mq); cmdq_req->cmdq_req_flags |= QBR; cmdq_req->mrq.cmd = &cmdq_req->cmd; cmdq_req->tag = req->tag; init_completion(&cmdq_req->mrq.completion); BUG_ON(req->tag > card->ext_csd.cmdq_depth); BUG_ON(test_and_set_bit(req->tag, &host->cmdq_ctx.active_reqs)); set_bit(CMDQ_STATE_DCMD_ACTIVE, &ctx_info->curr_state); return cmdq_req; } Loading Loading @@ -2483,8 +2483,13 @@ static int mmc_blk_cmdq_issue_discard_rq(struct mmc_queue *mq, } err = mmc_cmdq_erase(cmdq_req, card, from, nr, arg); clear_dcmd: if (err != -EAGAIN) { mmc_host_clk_hold(card->host); blk_complete_request(req); } else { pr_err("%s: err(%d) handled by cmdq-error handler\n", __func__, err); } out: return err ? 1 : 0; } Loading Loading @@ -2546,8 +2551,13 @@ static int mmc_blk_cmdq_issue_secdiscard_rq(struct mmc_queue *mq, MMC_SECURE_TRIM2_ARG); } clear_dcmd: if (err != -EAGAIN) { mmc_host_clk_hold(card->host); blk_complete_request(req); } else { pr_err("%s: err(%d) handled by cmdq-error handler\n", __func__, err); } out: return err ? 1 : 0; } Loading Loading @@ -2807,20 +2817,17 @@ static void mmc_blk_cmdq_reset(struct mmc_host *host, bool clear_all) } /** * is_cmdq_dcmd_req - Checks if tag belongs to DCMD request. * get_cmdq_req_by_tag - returns cmdq_rq based on tag. * @q: request_queue pointer. * @tag: tag number of request to check. * * This function checks if the request with tag number "tag" * is a DCMD request or not based on cmdq_req_flags set. * * returns true if DCMD req, otherwise false. */ static bool is_cmdq_dcmd_req(struct request_queue *q, int tag) static struct mmc_cmdq_req *get_cmdq_req_by_tag(struct request_queue *q, int tag) { struct request *req; struct mmc_queue_req *mq_rq; struct mmc_cmdq_req *cmdq_req; struct mmc_cmdq_req *cmdq_req = NULL; req = blk_queue_find_tag(q, tag); if (WARN_ON(!req)) Loading @@ -2829,9 +2836,8 @@ static bool is_cmdq_dcmd_req(struct request_queue *q, int tag) if (WARN_ON(!mq_rq)) goto out; cmdq_req = &(mq_rq->cmdq_req); return (cmdq_req->cmdq_req_flags & DCMD); out: return -ENOENT; return cmdq_req; } /** Loading @@ -2851,7 +2857,9 @@ static void mmc_blk_cmdq_reset_all(struct mmc_host *host, int err) struct mmc_cmdq_context_info *ctx_info = &host->cmdq_ctx; struct request_queue *q; int itag = 0; int ret = 0; struct mmc_cmdq_req *cmdq_req = NULL; struct mmc_request *dcmd_mrq; bool is_err_mrq_dcmd = false; if (WARN_ON(!mrq)) return; Loading @@ -2867,18 +2875,31 @@ static void mmc_blk_cmdq_reset_all(struct mmc_host *host, int err) mmc_blk_cmdq_reset(host, false); if (mrq->cmdq_req->cmdq_req_flags & DCMD) is_err_mrq_dcmd = true; for_each_set_bit(itag, &ctx_info->active_reqs, host->num_cq_slots) { ret = is_cmdq_dcmd_req(q, itag); if (WARN_ON(ret == -ENOENT)) cmdq_req = get_cmdq_req_by_tag(q, itag); if (WARN_ON(!cmdq_req)) continue; if (!ret) { if (!(cmdq_req->cmdq_req_flags & DCMD)) { WARN_ON(!test_and_clear_bit(itag, &ctx_info->data_active_reqs)); mmc_cmdq_post_req(host, itag, err); } else { clear_bit(CMDQ_STATE_DCMD_ACTIVE, &ctx_info->curr_state); dcmd_mrq = &cmdq_req->mrq; WARN_ON(!test_and_clear_bit(CMDQ_STATE_DCMD_ACTIVE, &ctx_info->curr_state)); pr_debug("%s: cmd(%u), req_op(%llu)\n", __func__, dcmd_mrq->cmd->opcode, req_op(dcmd_mrq->req)); if (!is_err_mrq_dcmd && !dcmd_mrq->cmd->error && (req_op(dcmd_mrq->req) == REQ_OP_SECURE_ERASE || req_op(dcmd_mrq->req) == REQ_OP_DISCARD)) { dcmd_mrq->cmd->error = -EAGAIN; complete(&dcmd_mrq->completion); } } WARN_ON(!test_and_clear_bit(itag, &ctx_info->active_reqs)); Loading drivers/mmc/core/core.c +1 −2 Original line number Diff line number Diff line Loading @@ -1854,7 +1854,6 @@ int mmc_cmdq_wait_for_dcmd(struct mmc_host *host, struct mmc_command *cmd = mrq->cmd; int err = 0; init_completion(&mrq->completion); mrq->done = mmc_cmdq_dcmd_req_done; err = mmc_cmdq_start_req(host, cmdq_req); if (err) Loading Loading @@ -3553,7 +3552,7 @@ static int mmc_cmdq_send_erase_cmd(struct mmc_cmdq_req *cmdq_req, if (err) { pr_err("mmc_erase: group start error %d, status %#x\n", err, cmd->resp[0]); return -EIO; return err; } return 0; } Loading drivers/mmc/core/mmc.c +0 −14 Original line number Diff line number Diff line Loading @@ -2967,15 +2967,6 @@ static int mmc_reset(struct mmc_host *host) mmc_pwrseq_reset(host); } /* Suspend clk scaling to avoid switching frequencies intermittently */ ret = mmc_suspend_clk_scaling(host); if (ret) { pr_err("%s: %s: fail to suspend clock scaling (%d)\n", mmc_hostname(host), __func__, ret); return ret; } ret = mmc_init_card(host, host->card->ocr, host->card); if (ret) { pr_err("%s: %s: mmc_init_card failed (%d)\n", Loading @@ -2983,11 +2974,6 @@ static int mmc_reset(struct mmc_host *host) return ret; } ret = mmc_resume_clk_scaling(host); if (ret) pr_err("%s: %s: fail to resume clock scaling (%d)\n", mmc_hostname(host), __func__, ret); return ret; } Loading drivers/mmc/host/cmdq_hci.c +46 −1 Original line number Diff line number Diff line Loading @@ -25,6 +25,8 @@ #include <linux/mmc/card.h> #include <linux/pm_runtime.h> #include <linux/workqueue.h> #include <linux/fault-inject.h> #include <linux/random.h> #include "cmdq_hci.h" #include "sdhci.h" Loading Loading @@ -899,6 +901,42 @@ static void cmdq_finish_data(struct mmc_host *mmc, unsigned int tag) mrq->done(mrq); } #ifdef CONFIG_FAIL_MMC_REQUEST static int cmdq_should_inject_err(struct mmc_host *mmc, int *err, unsigned int *dbr_set, unsigned int *status) { struct cmdq_host *cq_host = (struct cmdq_host *)mmc_cmdq_private(mmc); static const int errors[] = { -ETIMEDOUT, -EILSEQ, -EIO, }; *dbr_set = cmdq_readl(cq_host, CQTDBR); if (*dbr_set && should_fail(&mmc->fail_mmc_request, (prandom_u32() % 1024) * 512)) { pr_err("%s *** Before inducing force err, status (%d) error(%d) dbr(0x%x), active_reqs(0x%lx), data_active_reqs(0x%lx)\n", __func__, *status, *err, *dbr_set, mmc->cmdq_ctx.active_reqs, mmc->cmdq_ctx.data_active_reqs); *err = errors[prandom_u32() % ARRAY_SIZE(errors)]; *status = 0; pr_err("%s *** After inducing force err, status (%d) error(%d) dbr(0x%x), active_reqs(0x%lx), data_active_reqs(0x%lx)\n", __func__, *status, *err, *dbr_set, mmc->cmdq_ctx.active_reqs, mmc->cmdq_ctx.data_active_reqs); return true; } return false; } #else static int cmdq_should_inject_err(struct mmc_host *mmc, int *err, unsigned int *dbr_set, unsigned int *status) { return false; } #endif irqreturn_t cmdq_irq(struct mmc_host *mmc, int err) { u32 status; Loading @@ -910,9 +948,12 @@ irqreturn_t cmdq_irq(struct mmc_host *mmc, int err) u32 dbr_set = 0; u32 dev_pend_set = 0; int stat_err = 0; bool err_inject = false; status = cmdq_readl(cq_host, CQIS); err_inject = cmdq_should_inject_err(mmc, &err, &dbr_set, &status); if (!status && !err) return IRQ_NONE; MMC_TRACE(mmc, "%s: CQIS: 0x%x err: %d\n", Loading Loading @@ -958,6 +999,7 @@ irqreturn_t cmdq_irq(struct mmc_host *mmc, int err) * have caused such error, so check for any first * bit set in doorbell and proceed with an error. */ if (!dbr_set) dbr_set = cmdq_readl(cq_host, CQTDBR); if (!dbr_set) { pr_err("%s: spurious/force error interrupt\n", Loading Loading @@ -1099,6 +1141,9 @@ irqreturn_t cmdq_irq(struct mmc_host *mmc, int err) } } } if (err_inject && err == -ETIMEDOUT) goto out; cmdq_finish_data(mmc, tag); goto out; } else { Loading Loading
arch/arm64/configs/vendor/sdmsteppe_defconfig +1 −0 Original line number Diff line number Diff line Loading @@ -714,6 +714,7 @@ CONFIG_DEBUG_CREDENTIALS=y CONFIG_RCU_TORTURE_TEST=m CONFIG_FAULT_INJECTION=y CONFIG_FAIL_PAGE_ALLOC=y CONFIG_FAIL_MMC_REQUEST=y CONFIG_UFS_FAULT_INJECTION=y CONFIG_FAULT_INJECTION_DEBUG_FS=y CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y Loading
drivers/mmc/core/block.c +45 −24 Original line number Diff line number Diff line Loading @@ -2429,17 +2429,17 @@ static struct mmc_cmdq_req *mmc_blk_cmdq_prep_discard_req(struct mmc_queue *mq, struct mmc_cmdq_req *cmdq_req; struct mmc_queue_req *active_mqrq; BUG_ON(req->tag > card->ext_csd.cmdq_depth); BUG_ON(test_and_set_bit(req->tag, &host->cmdq_ctx.active_reqs)); set_bit(CMDQ_STATE_DCMD_ACTIVE, &ctx_info->curr_state); active_mqrq = req_to_mmc_queue_req(req); cmdq_req = mmc_cmdq_prep_dcmd(active_mqrq, mq); cmdq_req->cmdq_req_flags |= QBR; cmdq_req->mrq.cmd = &cmdq_req->cmd; cmdq_req->tag = req->tag; init_completion(&cmdq_req->mrq.completion); BUG_ON(req->tag > card->ext_csd.cmdq_depth); BUG_ON(test_and_set_bit(req->tag, &host->cmdq_ctx.active_reqs)); set_bit(CMDQ_STATE_DCMD_ACTIVE, &ctx_info->curr_state); return cmdq_req; } Loading Loading @@ -2483,8 +2483,13 @@ static int mmc_blk_cmdq_issue_discard_rq(struct mmc_queue *mq, } err = mmc_cmdq_erase(cmdq_req, card, from, nr, arg); clear_dcmd: if (err != -EAGAIN) { mmc_host_clk_hold(card->host); blk_complete_request(req); } else { pr_err("%s: err(%d) handled by cmdq-error handler\n", __func__, err); } out: return err ? 1 : 0; } Loading Loading @@ -2546,8 +2551,13 @@ static int mmc_blk_cmdq_issue_secdiscard_rq(struct mmc_queue *mq, MMC_SECURE_TRIM2_ARG); } clear_dcmd: if (err != -EAGAIN) { mmc_host_clk_hold(card->host); blk_complete_request(req); } else { pr_err("%s: err(%d) handled by cmdq-error handler\n", __func__, err); } out: return err ? 1 : 0; } Loading Loading @@ -2807,20 +2817,17 @@ static void mmc_blk_cmdq_reset(struct mmc_host *host, bool clear_all) } /** * is_cmdq_dcmd_req - Checks if tag belongs to DCMD request. * get_cmdq_req_by_tag - returns cmdq_rq based on tag. * @q: request_queue pointer. * @tag: tag number of request to check. * * This function checks if the request with tag number "tag" * is a DCMD request or not based on cmdq_req_flags set. * * returns true if DCMD req, otherwise false. */ static bool is_cmdq_dcmd_req(struct request_queue *q, int tag) static struct mmc_cmdq_req *get_cmdq_req_by_tag(struct request_queue *q, int tag) { struct request *req; struct mmc_queue_req *mq_rq; struct mmc_cmdq_req *cmdq_req; struct mmc_cmdq_req *cmdq_req = NULL; req = blk_queue_find_tag(q, tag); if (WARN_ON(!req)) Loading @@ -2829,9 +2836,8 @@ static bool is_cmdq_dcmd_req(struct request_queue *q, int tag) if (WARN_ON(!mq_rq)) goto out; cmdq_req = &(mq_rq->cmdq_req); return (cmdq_req->cmdq_req_flags & DCMD); out: return -ENOENT; return cmdq_req; } /** Loading @@ -2851,7 +2857,9 @@ static void mmc_blk_cmdq_reset_all(struct mmc_host *host, int err) struct mmc_cmdq_context_info *ctx_info = &host->cmdq_ctx; struct request_queue *q; int itag = 0; int ret = 0; struct mmc_cmdq_req *cmdq_req = NULL; struct mmc_request *dcmd_mrq; bool is_err_mrq_dcmd = false; if (WARN_ON(!mrq)) return; Loading @@ -2867,18 +2875,31 @@ static void mmc_blk_cmdq_reset_all(struct mmc_host *host, int err) mmc_blk_cmdq_reset(host, false); if (mrq->cmdq_req->cmdq_req_flags & DCMD) is_err_mrq_dcmd = true; for_each_set_bit(itag, &ctx_info->active_reqs, host->num_cq_slots) { ret = is_cmdq_dcmd_req(q, itag); if (WARN_ON(ret == -ENOENT)) cmdq_req = get_cmdq_req_by_tag(q, itag); if (WARN_ON(!cmdq_req)) continue; if (!ret) { if (!(cmdq_req->cmdq_req_flags & DCMD)) { WARN_ON(!test_and_clear_bit(itag, &ctx_info->data_active_reqs)); mmc_cmdq_post_req(host, itag, err); } else { clear_bit(CMDQ_STATE_DCMD_ACTIVE, &ctx_info->curr_state); dcmd_mrq = &cmdq_req->mrq; WARN_ON(!test_and_clear_bit(CMDQ_STATE_DCMD_ACTIVE, &ctx_info->curr_state)); pr_debug("%s: cmd(%u), req_op(%llu)\n", __func__, dcmd_mrq->cmd->opcode, req_op(dcmd_mrq->req)); if (!is_err_mrq_dcmd && !dcmd_mrq->cmd->error && (req_op(dcmd_mrq->req) == REQ_OP_SECURE_ERASE || req_op(dcmd_mrq->req) == REQ_OP_DISCARD)) { dcmd_mrq->cmd->error = -EAGAIN; complete(&dcmd_mrq->completion); } } WARN_ON(!test_and_clear_bit(itag, &ctx_info->active_reqs)); Loading
drivers/mmc/core/core.c +1 −2 Original line number Diff line number Diff line Loading @@ -1854,7 +1854,6 @@ int mmc_cmdq_wait_for_dcmd(struct mmc_host *host, struct mmc_command *cmd = mrq->cmd; int err = 0; init_completion(&mrq->completion); mrq->done = mmc_cmdq_dcmd_req_done; err = mmc_cmdq_start_req(host, cmdq_req); if (err) Loading Loading @@ -3553,7 +3552,7 @@ static int mmc_cmdq_send_erase_cmd(struct mmc_cmdq_req *cmdq_req, if (err) { pr_err("mmc_erase: group start error %d, status %#x\n", err, cmd->resp[0]); return -EIO; return err; } return 0; } Loading
drivers/mmc/core/mmc.c +0 −14 Original line number Diff line number Diff line Loading @@ -2967,15 +2967,6 @@ static int mmc_reset(struct mmc_host *host) mmc_pwrseq_reset(host); } /* Suspend clk scaling to avoid switching frequencies intermittently */ ret = mmc_suspend_clk_scaling(host); if (ret) { pr_err("%s: %s: fail to suspend clock scaling (%d)\n", mmc_hostname(host), __func__, ret); return ret; } ret = mmc_init_card(host, host->card->ocr, host->card); if (ret) { pr_err("%s: %s: mmc_init_card failed (%d)\n", Loading @@ -2983,11 +2974,6 @@ static int mmc_reset(struct mmc_host *host) return ret; } ret = mmc_resume_clk_scaling(host); if (ret) pr_err("%s: %s: fail to resume clock scaling (%d)\n", mmc_hostname(host), __func__, ret); return ret; } Loading
drivers/mmc/host/cmdq_hci.c +46 −1 Original line number Diff line number Diff line Loading @@ -25,6 +25,8 @@ #include <linux/mmc/card.h> #include <linux/pm_runtime.h> #include <linux/workqueue.h> #include <linux/fault-inject.h> #include <linux/random.h> #include "cmdq_hci.h" #include "sdhci.h" Loading Loading @@ -899,6 +901,42 @@ static void cmdq_finish_data(struct mmc_host *mmc, unsigned int tag) mrq->done(mrq); } #ifdef CONFIG_FAIL_MMC_REQUEST static int cmdq_should_inject_err(struct mmc_host *mmc, int *err, unsigned int *dbr_set, unsigned int *status) { struct cmdq_host *cq_host = (struct cmdq_host *)mmc_cmdq_private(mmc); static const int errors[] = { -ETIMEDOUT, -EILSEQ, -EIO, }; *dbr_set = cmdq_readl(cq_host, CQTDBR); if (*dbr_set && should_fail(&mmc->fail_mmc_request, (prandom_u32() % 1024) * 512)) { pr_err("%s *** Before inducing force err, status (%d) error(%d) dbr(0x%x), active_reqs(0x%lx), data_active_reqs(0x%lx)\n", __func__, *status, *err, *dbr_set, mmc->cmdq_ctx.active_reqs, mmc->cmdq_ctx.data_active_reqs); *err = errors[prandom_u32() % ARRAY_SIZE(errors)]; *status = 0; pr_err("%s *** After inducing force err, status (%d) error(%d) dbr(0x%x), active_reqs(0x%lx), data_active_reqs(0x%lx)\n", __func__, *status, *err, *dbr_set, mmc->cmdq_ctx.active_reqs, mmc->cmdq_ctx.data_active_reqs); return true; } return false; } #else static int cmdq_should_inject_err(struct mmc_host *mmc, int *err, unsigned int *dbr_set, unsigned int *status) { return false; } #endif irqreturn_t cmdq_irq(struct mmc_host *mmc, int err) { u32 status; Loading @@ -910,9 +948,12 @@ irqreturn_t cmdq_irq(struct mmc_host *mmc, int err) u32 dbr_set = 0; u32 dev_pend_set = 0; int stat_err = 0; bool err_inject = false; status = cmdq_readl(cq_host, CQIS); err_inject = cmdq_should_inject_err(mmc, &err, &dbr_set, &status); if (!status && !err) return IRQ_NONE; MMC_TRACE(mmc, "%s: CQIS: 0x%x err: %d\n", Loading Loading @@ -958,6 +999,7 @@ irqreturn_t cmdq_irq(struct mmc_host *mmc, int err) * have caused such error, so check for any first * bit set in doorbell and proceed with an error. */ if (!dbr_set) dbr_set = cmdq_readl(cq_host, CQTDBR); if (!dbr_set) { pr_err("%s: spurious/force error interrupt\n", Loading Loading @@ -1099,6 +1141,9 @@ irqreturn_t cmdq_irq(struct mmc_host *mmc, int err) } } } if (err_inject && err == -ETIMEDOUT) goto out; cmdq_finish_data(mmc, tag); goto out; } else { Loading