Loading drivers/mmc/card/block.c +170 −88 Original line number Diff line number Diff line Loading @@ -2895,24 +2895,120 @@ EXPORT_SYMBOL(mmc_blk_cmdq_issue_flush_rq); static void mmc_blk_cmdq_reset(struct mmc_host *host, bool clear_all) { if (!host->cmdq_ops->reset) return; int err = 0; if (!test_bit(CMDQ_STATE_HALT, &host->cmdq_ctx.curr_state)) { if (mmc_cmdq_halt(host, true)) { pr_err("%s: halt failed\n", mmc_hostname(host)); goto reset; } } if (clear_all) mmc_cmdq_discard_queue(host, 0); reset: mmc_hw_reset(host); mmc_host_clk_hold(host); host->cmdq_ops->reset(host, true); host->cmdq_ops->disable(host, true); mmc_host_clk_release(host); err = mmc_cmdq_hw_reset(host); if (err && err != -EOPNOTSUPP) { pr_err("%s: failed to cmdq_hw_reset err = %d\n", mmc_hostname(host), err); mmc_host_clk_hold(host); host->cmdq_ops->enable(host); mmc_host_clk_release(host); mmc_cmdq_halt(host, false); goto out; } /* * CMDQ HW reset would have already made CQE * in unhalted state, but reflect the same * in software state of cmdq_ctx. */ mmc_host_clr_halt(host); out: return; } /** * is_cmdq_dcmd_req - Checks if tag belongs to DCMD request. * @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) { struct request *req; struct mmc_queue_req *mq_rq; struct mmc_cmdq_req *cmdq_req; req = blk_queue_find_tag(q, tag); if (WARN_ON(!req)) goto out; mq_rq = req->special; if (WARN_ON(!mq_rq)) goto out; cmdq_req = &(mq_rq->cmdq_req); return (cmdq_req->cmdq_req_flags & DCMD); out: return -ENOENT; } /** * mmc_blk_cmdq_reset_all - Reset everything for CMDQ block request. * @host: mmc_host pointer. * @err: error for which reset is performed. * * This function implements reset_all functionality for * cmdq. It resets the controller, power cycle the card, * and invalidate all busy tags(requeue all request back to * elevator). */ static void mmc_blk_cmdq_reset_all(struct mmc_host *host, int err) { struct mmc_request *mrq = host->err_mrq; struct mmc_card *card = host->card; struct mmc_cmdq_context_info *ctx_info = &host->cmdq_ctx; struct request_queue *q; int itag = 0; int ret = 0; if (WARN_ON(!mrq)) return; q = mrq->req->q; WARN_ON(!test_bit(CMDQ_STATE_ERR, &ctx_info->curr_state)); pr_debug("%s: %s: active_reqs = %lu, clk_requests = %d\n", mmc_hostname(host), __func__, ctx_info->active_reqs, host->clk_requests); mmc_blk_cmdq_reset(host, false); 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)) continue; if (!ret) { WARN_ON(!test_and_clear_bit(itag, &ctx_info->data_active_reqs)); } else { clear_bit(CMDQ_STATE_DCMD_ACTIVE, &ctx_info->curr_state); } mmc_cmdq_post_req(host, itag, err); WARN_ON(!test_and_clear_bit(itag, &ctx_info->active_reqs)); mmc_host_clk_release(host); clear_bit(CMDQ_STATE_HALT, &host->cmdq_ctx.curr_state); mmc_put_card(card); } spin_lock_irq(q->queue_lock); blk_queue_invalidate_tags(q); spin_unlock_irq(q->queue_lock); } static void mmc_blk_cmdq_shutdown(struct mmc_queue *mq) Loading Loading @@ -2955,6 +3051,7 @@ static enum blk_eh_timer_return mmc_blk_cmdq_req_timed_out(struct request *req) struct mmc_queue_req *mq_rq = req->special; struct mmc_request *mrq; struct mmc_cmdq_req *cmdq_req; struct mmc_cmdq_context_info *ctx_info = &host->cmdq_ctx; BUG_ON(!host); Loading @@ -2980,32 +3077,40 @@ static enum blk_eh_timer_return mmc_blk_cmdq_req_timed_out(struct request *req) else mrq->data->error = -ETIMEDOUT; BUG_ON(host->err_mrq != NULL); host->err_mrq = mrq; if (test_bit(CMDQ_STATE_REQ_TIMED_OUT, &ctx_info->curr_state) || test_bit(CMDQ_STATE_ERR, &ctx_info->curr_state)) return BLK_EH_NOT_HANDLED; mmc_host_clk_release(mrq->host); set_bit(CMDQ_STATE_REQ_TIMED_OUT, &ctx_info->curr_state); return BLK_EH_HANDLED; } /* * mmc_blk_cmdq_err: error handling of cmdq error requests. * Function should be called in context of error out request * which has claim_host and rpm acquired. * This may be called with CQ engine halted. Make sure to * unhalt it after error recovery. * * TODO: Currently cmdq error handler does reset_all in case * of any erorr. Need to optimize error handling. */ static void mmc_blk_cmdq_err(struct mmc_queue *mq) { int err; int retry = 0; int gen_err; u32 status; struct mmc_host *host = mq->card->host; struct mmc_request *mrq = host->err_mrq; struct mmc_card *card = mq->card; struct mmc_cmdq_context_info *ctx_info = &host->cmdq_ctx; struct request_queue *q = mrq->req->q; int tag = mrq->req->tag; struct request_queue *q; int err; pm_runtime_get_sync(&card->dev); mmc_host_clk_hold(host); host->cmdq_ops->dumpstate(host); mmc_host_clk_release(host); if (WARN_ON(!mrq)) return; q = mrq->req->q; err = mmc_cmdq_halt(host, true); if (err) { pr_err("halt: failed: %d\n", err); Loading @@ -3014,74 +3119,44 @@ static void mmc_blk_cmdq_err(struct mmc_queue *mq) /* RED error - Fatal: requires reset */ if (mrq->cmdq_req->resp_err) { err = mrq->cmdq_req->resp_err; pr_crit("%s: Response error detected: Device in bad state\n", mmc_hostname(host)); blk_end_request_all(mrq->req, -EIO); goto reset; } if (mrq->data && mrq->data->error) { blk_end_request_all(mrq->req, mrq->data->error); for (; retry < MAX_RETRIES; retry++) { err = get_card_status(card, &status, 0); if (!err) break; } if (err) { pr_err("%s: No response from card !!!\n", mmc_hostname(host)); goto reset; } if (R1_CURRENT_STATE(status) == R1_STATE_DATA || R1_CURRENT_STATE(status) == R1_STATE_RCV) { err = send_stop(card, MMC_CMDQ_STOP_TIMEOUT_MS, mrq->req, &gen_err, &status); if (err) { pr_err("%s: error %d sending stop (%d) command\n", mmc_hostname(host), err, status); goto reset; } } if (mmc_cmdq_discard_queue(host, tag)) goto reset; else goto unhalt; } /* * In case of software request time-out, we schedule err work only for * the first error out request and handles all other request in flight * here. */ if (test_bit(CMDQ_STATE_REQ_TIMED_OUT, &ctx_info->curr_state)) { err = -ETIMEDOUT; } else if (mrq->data && mrq->data->error) { err = mrq->data->error; } else if (mrq->cmd && mrq->cmd->error) { /* DCMD commands */ if (mrq->cmd && mrq->cmd->error) { err = mrq->cmd->error; /* * Notify completion for non flush commands like discard * that wait for DCMD finish. */ if (!(mrq->req->cmd_flags & REQ_FLUSH)) { complete(&mrq->completion); goto reset; } clear_bit(CMDQ_STATE_DCMD_ACTIVE, &ctx_info->curr_state); blk_end_request_all(mrq->req, mrq->cmd->error); } reset: spin_lock_irq(mq->queue->queue_lock); blk_queue_invalidate_tags(q); spin_unlock_irq(mq->queue->queue_lock); mmc_blk_cmdq_reset(host, true); goto out; unhalt: mmc_blk_cmdq_reset_all(host, err); if (mrq->cmdq_req->resp_err) mrq->cmdq_req->resp_err = false; mmc_cmdq_halt(host, false); out: host->err_mrq = NULL; pm_runtime_mark_last_busy(&card->dev); clear_bit(CMDQ_STATE_ERR, &ctx_info->curr_state); clear_bit(CMDQ_STATE_REQ_TIMED_OUT, &ctx_info->curr_state); WARN_ON(!test_and_clear_bit(CMDQ_STATE_ERR, &ctx_info->curr_state)); wake_up(&ctx_info->wait); __mmc_put_card(card); } /* invoked by block layer in softirq context */ Loading @@ -3101,31 +3176,38 @@ void mmc_blk_cmdq_complete_rq(struct request *rq) else if (mrq->data && mrq->data->error) err = mrq->data->error; /* clear pending request */ BUG_ON(!test_and_clear_bit(cmdq_req->tag, &ctx_info->active_reqs)); if (cmdq_req->cmdq_req_flags & DCMD) is_dcmd = true; else BUG_ON(!test_and_clear_bit(cmdq_req->tag, &ctx_info->data_active_reqs)); mmc_cmdq_post_req(host, cmdq_req->tag, err); if (err) { pr_err("%s: %s: txfr error: %d\n", mmc_hostname(mrq->host), __func__, err); if (err || cmdq_req->resp_err) { pr_err("%s: %s: txfr error(%d)/resp_err(%d)\n", mmc_hostname(mrq->host), __func__, err, cmdq_req->resp_err); if (test_bit(CMDQ_STATE_ERR, &ctx_info->curr_state)) { pr_err("%s: CQ in error state, ending current req: %d\n", __func__, err); blk_end_request_all(rq, err); } else { set_bit(CMDQ_STATE_ERR, &ctx_info->curr_state); BUG_ON(host->err_mrq != NULL); host->err_mrq = mrq; schedule_work(&mq->cmdq_err_work); } goto out; } /* * In case of error CMDQ is expected to be either in halted * or disable state so cannot receive any completion of * other requests. */ BUG_ON(test_bit(CMDQ_STATE_ERR, &ctx_info->curr_state)); /* clear pending request */ BUG_ON(!test_and_clear_bit(cmdq_req->tag, &ctx_info->active_reqs)); if (cmdq_req->cmdq_req_flags & DCMD) is_dcmd = true; else BUG_ON(!test_and_clear_bit(cmdq_req->tag, &ctx_info->data_active_reqs)); mmc_cmdq_post_req(host, cmdq_req->tag, err); if (cmdq_req->cmdq_req_flags & DCMD) { clear_bit(CMDQ_STATE_DCMD_ACTIVE, &ctx_info->curr_state); blk_end_request_all(rq, err); Loading @@ -3137,10 +3219,11 @@ void mmc_blk_cmdq_complete_rq(struct request *rq) out: mmc_cmdq_clk_scaling_stop_busy(host, true, is_dcmd); if (!test_bit(CMDQ_STATE_ERR, &ctx_info->curr_state)) if (!test_bit(CMDQ_STATE_ERR, &ctx_info->curr_state)) { wake_up(&ctx_info->wait); mmc_put_card(host->card); } if (!ctx_info->active_reqs) wake_up_interruptible(&host->cmdq_ctx.queue_empty_wq); Loading @@ -3155,7 +3238,6 @@ void mmc_blk_cmdq_req_done(struct mmc_request *mrq) { struct request *req = mrq->req; mmc_host_clk_release(mrq->host); blk_complete_request(req); } EXPORT_SYMBOL(mmc_blk_cmdq_req_done); Loading drivers/mmc/host/cmdq_hci.c +0 −1 Original line number Diff line number Diff line Loading @@ -881,7 +881,6 @@ skip_cqterri: mrq->cmdq_req->resp_arg = cmdq_readl(cq_host, CQCRA); } mmc->err_mrq = mrq; cmdq_finish_data(mmc, tag); } Loading include/linux/mmc/host.h +1 −0 Original line number Diff line number Diff line Loading @@ -256,6 +256,7 @@ struct mmc_cmdq_context_info { #define CMDQ_STATE_DCMD_ACTIVE 1 #define CMDQ_STATE_HALT 2 #define CMDQ_STATE_CQ_DISABLE 3 #define CMDQ_STATE_REQ_TIMED_OUT 4 wait_queue_head_t queue_empty_wq; wait_queue_head_t wait; int active_small_sector_read_reqs; Loading Loading
drivers/mmc/card/block.c +170 −88 Original line number Diff line number Diff line Loading @@ -2895,24 +2895,120 @@ EXPORT_SYMBOL(mmc_blk_cmdq_issue_flush_rq); static void mmc_blk_cmdq_reset(struct mmc_host *host, bool clear_all) { if (!host->cmdq_ops->reset) return; int err = 0; if (!test_bit(CMDQ_STATE_HALT, &host->cmdq_ctx.curr_state)) { if (mmc_cmdq_halt(host, true)) { pr_err("%s: halt failed\n", mmc_hostname(host)); goto reset; } } if (clear_all) mmc_cmdq_discard_queue(host, 0); reset: mmc_hw_reset(host); mmc_host_clk_hold(host); host->cmdq_ops->reset(host, true); host->cmdq_ops->disable(host, true); mmc_host_clk_release(host); err = mmc_cmdq_hw_reset(host); if (err && err != -EOPNOTSUPP) { pr_err("%s: failed to cmdq_hw_reset err = %d\n", mmc_hostname(host), err); mmc_host_clk_hold(host); host->cmdq_ops->enable(host); mmc_host_clk_release(host); mmc_cmdq_halt(host, false); goto out; } /* * CMDQ HW reset would have already made CQE * in unhalted state, but reflect the same * in software state of cmdq_ctx. */ mmc_host_clr_halt(host); out: return; } /** * is_cmdq_dcmd_req - Checks if tag belongs to DCMD request. * @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) { struct request *req; struct mmc_queue_req *mq_rq; struct mmc_cmdq_req *cmdq_req; req = blk_queue_find_tag(q, tag); if (WARN_ON(!req)) goto out; mq_rq = req->special; if (WARN_ON(!mq_rq)) goto out; cmdq_req = &(mq_rq->cmdq_req); return (cmdq_req->cmdq_req_flags & DCMD); out: return -ENOENT; } /** * mmc_blk_cmdq_reset_all - Reset everything for CMDQ block request. * @host: mmc_host pointer. * @err: error for which reset is performed. * * This function implements reset_all functionality for * cmdq. It resets the controller, power cycle the card, * and invalidate all busy tags(requeue all request back to * elevator). */ static void mmc_blk_cmdq_reset_all(struct mmc_host *host, int err) { struct mmc_request *mrq = host->err_mrq; struct mmc_card *card = host->card; struct mmc_cmdq_context_info *ctx_info = &host->cmdq_ctx; struct request_queue *q; int itag = 0; int ret = 0; if (WARN_ON(!mrq)) return; q = mrq->req->q; WARN_ON(!test_bit(CMDQ_STATE_ERR, &ctx_info->curr_state)); pr_debug("%s: %s: active_reqs = %lu, clk_requests = %d\n", mmc_hostname(host), __func__, ctx_info->active_reqs, host->clk_requests); mmc_blk_cmdq_reset(host, false); 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)) continue; if (!ret) { WARN_ON(!test_and_clear_bit(itag, &ctx_info->data_active_reqs)); } else { clear_bit(CMDQ_STATE_DCMD_ACTIVE, &ctx_info->curr_state); } mmc_cmdq_post_req(host, itag, err); WARN_ON(!test_and_clear_bit(itag, &ctx_info->active_reqs)); mmc_host_clk_release(host); clear_bit(CMDQ_STATE_HALT, &host->cmdq_ctx.curr_state); mmc_put_card(card); } spin_lock_irq(q->queue_lock); blk_queue_invalidate_tags(q); spin_unlock_irq(q->queue_lock); } static void mmc_blk_cmdq_shutdown(struct mmc_queue *mq) Loading Loading @@ -2955,6 +3051,7 @@ static enum blk_eh_timer_return mmc_blk_cmdq_req_timed_out(struct request *req) struct mmc_queue_req *mq_rq = req->special; struct mmc_request *mrq; struct mmc_cmdq_req *cmdq_req; struct mmc_cmdq_context_info *ctx_info = &host->cmdq_ctx; BUG_ON(!host); Loading @@ -2980,32 +3077,40 @@ static enum blk_eh_timer_return mmc_blk_cmdq_req_timed_out(struct request *req) else mrq->data->error = -ETIMEDOUT; BUG_ON(host->err_mrq != NULL); host->err_mrq = mrq; if (test_bit(CMDQ_STATE_REQ_TIMED_OUT, &ctx_info->curr_state) || test_bit(CMDQ_STATE_ERR, &ctx_info->curr_state)) return BLK_EH_NOT_HANDLED; mmc_host_clk_release(mrq->host); set_bit(CMDQ_STATE_REQ_TIMED_OUT, &ctx_info->curr_state); return BLK_EH_HANDLED; } /* * mmc_blk_cmdq_err: error handling of cmdq error requests. * Function should be called in context of error out request * which has claim_host and rpm acquired. * This may be called with CQ engine halted. Make sure to * unhalt it after error recovery. * * TODO: Currently cmdq error handler does reset_all in case * of any erorr. Need to optimize error handling. */ static void mmc_blk_cmdq_err(struct mmc_queue *mq) { int err; int retry = 0; int gen_err; u32 status; struct mmc_host *host = mq->card->host; struct mmc_request *mrq = host->err_mrq; struct mmc_card *card = mq->card; struct mmc_cmdq_context_info *ctx_info = &host->cmdq_ctx; struct request_queue *q = mrq->req->q; int tag = mrq->req->tag; struct request_queue *q; int err; pm_runtime_get_sync(&card->dev); mmc_host_clk_hold(host); host->cmdq_ops->dumpstate(host); mmc_host_clk_release(host); if (WARN_ON(!mrq)) return; q = mrq->req->q; err = mmc_cmdq_halt(host, true); if (err) { pr_err("halt: failed: %d\n", err); Loading @@ -3014,74 +3119,44 @@ static void mmc_blk_cmdq_err(struct mmc_queue *mq) /* RED error - Fatal: requires reset */ if (mrq->cmdq_req->resp_err) { err = mrq->cmdq_req->resp_err; pr_crit("%s: Response error detected: Device in bad state\n", mmc_hostname(host)); blk_end_request_all(mrq->req, -EIO); goto reset; } if (mrq->data && mrq->data->error) { blk_end_request_all(mrq->req, mrq->data->error); for (; retry < MAX_RETRIES; retry++) { err = get_card_status(card, &status, 0); if (!err) break; } if (err) { pr_err("%s: No response from card !!!\n", mmc_hostname(host)); goto reset; } if (R1_CURRENT_STATE(status) == R1_STATE_DATA || R1_CURRENT_STATE(status) == R1_STATE_RCV) { err = send_stop(card, MMC_CMDQ_STOP_TIMEOUT_MS, mrq->req, &gen_err, &status); if (err) { pr_err("%s: error %d sending stop (%d) command\n", mmc_hostname(host), err, status); goto reset; } } if (mmc_cmdq_discard_queue(host, tag)) goto reset; else goto unhalt; } /* * In case of software request time-out, we schedule err work only for * the first error out request and handles all other request in flight * here. */ if (test_bit(CMDQ_STATE_REQ_TIMED_OUT, &ctx_info->curr_state)) { err = -ETIMEDOUT; } else if (mrq->data && mrq->data->error) { err = mrq->data->error; } else if (mrq->cmd && mrq->cmd->error) { /* DCMD commands */ if (mrq->cmd && mrq->cmd->error) { err = mrq->cmd->error; /* * Notify completion for non flush commands like discard * that wait for DCMD finish. */ if (!(mrq->req->cmd_flags & REQ_FLUSH)) { complete(&mrq->completion); goto reset; } clear_bit(CMDQ_STATE_DCMD_ACTIVE, &ctx_info->curr_state); blk_end_request_all(mrq->req, mrq->cmd->error); } reset: spin_lock_irq(mq->queue->queue_lock); blk_queue_invalidate_tags(q); spin_unlock_irq(mq->queue->queue_lock); mmc_blk_cmdq_reset(host, true); goto out; unhalt: mmc_blk_cmdq_reset_all(host, err); if (mrq->cmdq_req->resp_err) mrq->cmdq_req->resp_err = false; mmc_cmdq_halt(host, false); out: host->err_mrq = NULL; pm_runtime_mark_last_busy(&card->dev); clear_bit(CMDQ_STATE_ERR, &ctx_info->curr_state); clear_bit(CMDQ_STATE_REQ_TIMED_OUT, &ctx_info->curr_state); WARN_ON(!test_and_clear_bit(CMDQ_STATE_ERR, &ctx_info->curr_state)); wake_up(&ctx_info->wait); __mmc_put_card(card); } /* invoked by block layer in softirq context */ Loading @@ -3101,31 +3176,38 @@ void mmc_blk_cmdq_complete_rq(struct request *rq) else if (mrq->data && mrq->data->error) err = mrq->data->error; /* clear pending request */ BUG_ON(!test_and_clear_bit(cmdq_req->tag, &ctx_info->active_reqs)); if (cmdq_req->cmdq_req_flags & DCMD) is_dcmd = true; else BUG_ON(!test_and_clear_bit(cmdq_req->tag, &ctx_info->data_active_reqs)); mmc_cmdq_post_req(host, cmdq_req->tag, err); if (err) { pr_err("%s: %s: txfr error: %d\n", mmc_hostname(mrq->host), __func__, err); if (err || cmdq_req->resp_err) { pr_err("%s: %s: txfr error(%d)/resp_err(%d)\n", mmc_hostname(mrq->host), __func__, err, cmdq_req->resp_err); if (test_bit(CMDQ_STATE_ERR, &ctx_info->curr_state)) { pr_err("%s: CQ in error state, ending current req: %d\n", __func__, err); blk_end_request_all(rq, err); } else { set_bit(CMDQ_STATE_ERR, &ctx_info->curr_state); BUG_ON(host->err_mrq != NULL); host->err_mrq = mrq; schedule_work(&mq->cmdq_err_work); } goto out; } /* * In case of error CMDQ is expected to be either in halted * or disable state so cannot receive any completion of * other requests. */ BUG_ON(test_bit(CMDQ_STATE_ERR, &ctx_info->curr_state)); /* clear pending request */ BUG_ON(!test_and_clear_bit(cmdq_req->tag, &ctx_info->active_reqs)); if (cmdq_req->cmdq_req_flags & DCMD) is_dcmd = true; else BUG_ON(!test_and_clear_bit(cmdq_req->tag, &ctx_info->data_active_reqs)); mmc_cmdq_post_req(host, cmdq_req->tag, err); if (cmdq_req->cmdq_req_flags & DCMD) { clear_bit(CMDQ_STATE_DCMD_ACTIVE, &ctx_info->curr_state); blk_end_request_all(rq, err); Loading @@ -3137,10 +3219,11 @@ void mmc_blk_cmdq_complete_rq(struct request *rq) out: mmc_cmdq_clk_scaling_stop_busy(host, true, is_dcmd); if (!test_bit(CMDQ_STATE_ERR, &ctx_info->curr_state)) if (!test_bit(CMDQ_STATE_ERR, &ctx_info->curr_state)) { wake_up(&ctx_info->wait); mmc_put_card(host->card); } if (!ctx_info->active_reqs) wake_up_interruptible(&host->cmdq_ctx.queue_empty_wq); Loading @@ -3155,7 +3238,6 @@ void mmc_blk_cmdq_req_done(struct mmc_request *mrq) { struct request *req = mrq->req; mmc_host_clk_release(mrq->host); blk_complete_request(req); } EXPORT_SYMBOL(mmc_blk_cmdq_req_done); Loading
drivers/mmc/host/cmdq_hci.c +0 −1 Original line number Diff line number Diff line Loading @@ -881,7 +881,6 @@ skip_cqterri: mrq->cmdq_req->resp_arg = cmdq_readl(cq_host, CQCRA); } mmc->err_mrq = mrq; cmdq_finish_data(mmc, tag); } Loading
include/linux/mmc/host.h +1 −0 Original line number Diff line number Diff line Loading @@ -256,6 +256,7 @@ struct mmc_cmdq_context_info { #define CMDQ_STATE_DCMD_ACTIVE 1 #define CMDQ_STATE_HALT 2 #define CMDQ_STATE_CQ_DISABLE 3 #define CMDQ_STATE_REQ_TIMED_OUT 4 wait_queue_head_t queue_empty_wq; wait_queue_head_t wait; int active_small_sector_read_reqs; Loading