Loading drivers/mmc/card/block.c +3 −0 Original line number Diff line number Diff line Loading @@ -3610,6 +3610,9 @@ void mmc_blk_cmdq_complete_rq(struct request *rq) if (!ctx_info->active_reqs) wake_up_interruptible(&host->cmdq_ctx.queue_empty_wq); if (blk_queue_stopped(mq->queue) && !ctx_info->active_reqs) complete(&mq->cmdq_shutdown_complete); return; } Loading drivers/mmc/card/queue.c +22 −3 Original line number Diff line number Diff line Loading @@ -100,7 +100,8 @@ static inline void mmc_cmdq_ready_wait(struct mmc_host *host, * 4. cmdq state shouldn't be in error state. * 5. free tag available to process the new request. */ wait_event(ctx->wait, mmc_peek_request(mq) && wait_event(ctx->wait, kthread_should_stop() || (mmc_peek_request(mq) && !(((req_op(mq->cmdq_req_peeked) == REQ_OP_FLUSH) || (req_op(mq->cmdq_req_peeked) == REQ_OP_DISCARD)) && test_bit(CMDQ_STATE_DCMD_ACTIVE, &ctx->curr_state)) Loading @@ -109,7 +110,7 @@ static inline void mmc_cmdq_ready_wait(struct mmc_host *host, && !(!host->card->part_curr && mmc_host_cq_disable(host) && !mmc_card_suspended(host->card)) && !test_bit(CMDQ_STATE_ERR, &ctx->curr_state) && !mmc_check_blk_queue_start_tag(q, mq->cmdq_req_peeked)); && !mmc_check_blk_queue_start_tag(q, mq->cmdq_req_peeked))); } static int mmc_cmdq_thread(void *d) Loading @@ -127,6 +128,8 @@ static int mmc_cmdq_thread(void *d) int ret = 0; mmc_cmdq_ready_wait(host, mq); if (kthread_should_stop()) break; ret = mq->cmdq_issue_fn(mq, mq->cmdq_req_peeked); /* Loading Loading @@ -668,6 +671,7 @@ int mmc_cmdq_init(struct mmc_queue *mq, struct mmc_card *card) blk_queue_softirq_done(mq->queue, mmc_cmdq_softirq_done); INIT_WORK(&mq->cmdq_err_work, mmc_cmdq_error_work); init_completion(&mq->cmdq_shutdown_complete); init_completion(&mq->cmdq_pending_req_done); blk_queue_rq_timed_out(mq->queue, mmc_cmdq_rq_timed_out); Loading Loading @@ -724,7 +728,22 @@ int mmc_queue_suspend(struct mmc_queue *mq, int wait) goto out; if (wait) { blk_cleanup_queue(q); /* * After blk_stop_queue is called, wait for all * active_reqs to complete. * Then wait for cmdq thread to exit before calling * cmdq shutdown to avoid race between issuing * requests and shutdown of cmdq. */ spin_lock_irqsave(q->queue_lock, flags); blk_stop_queue(q); spin_unlock_irqrestore(q->queue_lock, flags); if (host->cmdq_ctx.active_reqs) wait_for_completion( &mq->cmdq_shutdown_complete); kthread_stop(mq->thread); mq->cmdq_shutdown(mq); } else { spin_lock_irqsave(q->queue_lock, flags); Loading drivers/mmc/card/queue.h +1 −0 Original line number Diff line number Diff line Loading @@ -77,6 +77,7 @@ struct mmc_queue { struct work_struct cmdq_err_work; struct completion cmdq_pending_req_done; struct completion cmdq_shutdown_complete; struct request *cmdq_req_peeked; int (*err_check_fn)(struct mmc_card *, struct mmc_async_req *); void (*packed_test_fn)(struct request_queue *, struct mmc_queue_req *); Loading Loading
drivers/mmc/card/block.c +3 −0 Original line number Diff line number Diff line Loading @@ -3610,6 +3610,9 @@ void mmc_blk_cmdq_complete_rq(struct request *rq) if (!ctx_info->active_reqs) wake_up_interruptible(&host->cmdq_ctx.queue_empty_wq); if (blk_queue_stopped(mq->queue) && !ctx_info->active_reqs) complete(&mq->cmdq_shutdown_complete); return; } Loading
drivers/mmc/card/queue.c +22 −3 Original line number Diff line number Diff line Loading @@ -100,7 +100,8 @@ static inline void mmc_cmdq_ready_wait(struct mmc_host *host, * 4. cmdq state shouldn't be in error state. * 5. free tag available to process the new request. */ wait_event(ctx->wait, mmc_peek_request(mq) && wait_event(ctx->wait, kthread_should_stop() || (mmc_peek_request(mq) && !(((req_op(mq->cmdq_req_peeked) == REQ_OP_FLUSH) || (req_op(mq->cmdq_req_peeked) == REQ_OP_DISCARD)) && test_bit(CMDQ_STATE_DCMD_ACTIVE, &ctx->curr_state)) Loading @@ -109,7 +110,7 @@ static inline void mmc_cmdq_ready_wait(struct mmc_host *host, && !(!host->card->part_curr && mmc_host_cq_disable(host) && !mmc_card_suspended(host->card)) && !test_bit(CMDQ_STATE_ERR, &ctx->curr_state) && !mmc_check_blk_queue_start_tag(q, mq->cmdq_req_peeked)); && !mmc_check_blk_queue_start_tag(q, mq->cmdq_req_peeked))); } static int mmc_cmdq_thread(void *d) Loading @@ -127,6 +128,8 @@ static int mmc_cmdq_thread(void *d) int ret = 0; mmc_cmdq_ready_wait(host, mq); if (kthread_should_stop()) break; ret = mq->cmdq_issue_fn(mq, mq->cmdq_req_peeked); /* Loading Loading @@ -668,6 +671,7 @@ int mmc_cmdq_init(struct mmc_queue *mq, struct mmc_card *card) blk_queue_softirq_done(mq->queue, mmc_cmdq_softirq_done); INIT_WORK(&mq->cmdq_err_work, mmc_cmdq_error_work); init_completion(&mq->cmdq_shutdown_complete); init_completion(&mq->cmdq_pending_req_done); blk_queue_rq_timed_out(mq->queue, mmc_cmdq_rq_timed_out); Loading Loading @@ -724,7 +728,22 @@ int mmc_queue_suspend(struct mmc_queue *mq, int wait) goto out; if (wait) { blk_cleanup_queue(q); /* * After blk_stop_queue is called, wait for all * active_reqs to complete. * Then wait for cmdq thread to exit before calling * cmdq shutdown to avoid race between issuing * requests and shutdown of cmdq. */ spin_lock_irqsave(q->queue_lock, flags); blk_stop_queue(q); spin_unlock_irqrestore(q->queue_lock, flags); if (host->cmdq_ctx.active_reqs) wait_for_completion( &mq->cmdq_shutdown_complete); kthread_stop(mq->thread); mq->cmdq_shutdown(mq); } else { spin_lock_irqsave(q->queue_lock, flags); Loading
drivers/mmc/card/queue.h +1 −0 Original line number Diff line number Diff line Loading @@ -77,6 +77,7 @@ struct mmc_queue { struct work_struct cmdq_err_work; struct completion cmdq_pending_req_done; struct completion cmdq_shutdown_complete; struct request *cmdq_req_peeked; int (*err_check_fn)(struct mmc_card *, struct mmc_async_req *); void (*packed_test_fn)(struct request_queue *, struct mmc_queue_req *); Loading