162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#ifndef MMC_QUEUE_H
362306a36Sopenharmony_ci#define MMC_QUEUE_H
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#include <linux/types.h>
662306a36Sopenharmony_ci#include <linux/blkdev.h>
762306a36Sopenharmony_ci#include <linux/blk-mq.h>
862306a36Sopenharmony_ci#include <linux/mmc/core.h>
962306a36Sopenharmony_ci#include <linux/mmc/host.h>
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_cienum mmc_issued {
1262306a36Sopenharmony_ci	MMC_REQ_STARTED,
1362306a36Sopenharmony_ci	MMC_REQ_BUSY,
1462306a36Sopenharmony_ci	MMC_REQ_FAILED_TO_START,
1562306a36Sopenharmony_ci	MMC_REQ_FINISHED,
1662306a36Sopenharmony_ci};
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_cienum mmc_issue_type {
1962306a36Sopenharmony_ci	MMC_ISSUE_SYNC,
2062306a36Sopenharmony_ci	MMC_ISSUE_DCMD,
2162306a36Sopenharmony_ci	MMC_ISSUE_ASYNC,
2262306a36Sopenharmony_ci	MMC_ISSUE_MAX,
2362306a36Sopenharmony_ci};
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_cistatic inline struct mmc_queue_req *req_to_mmc_queue_req(struct request *rq)
2662306a36Sopenharmony_ci{
2762306a36Sopenharmony_ci	return blk_mq_rq_to_pdu(rq);
2862306a36Sopenharmony_ci}
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_cistruct mmc_queue_req;
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_cistatic inline struct request *mmc_queue_req_to_req(struct mmc_queue_req *mqr)
3362306a36Sopenharmony_ci{
3462306a36Sopenharmony_ci	return blk_mq_rq_from_pdu(mqr);
3562306a36Sopenharmony_ci}
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_cistruct mmc_blk_data;
3862306a36Sopenharmony_cistruct mmc_blk_ioc_data;
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_cistruct mmc_blk_request {
4162306a36Sopenharmony_ci	struct mmc_request	mrq;
4262306a36Sopenharmony_ci	struct mmc_command	sbc;
4362306a36Sopenharmony_ci	struct mmc_command	cmd;
4462306a36Sopenharmony_ci	struct mmc_command	stop;
4562306a36Sopenharmony_ci	struct mmc_data		data;
4662306a36Sopenharmony_ci};
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci/**
4962306a36Sopenharmony_ci * enum mmc_drv_op - enumerates the operations in the mmc_queue_req
5062306a36Sopenharmony_ci * @MMC_DRV_OP_IOCTL: ioctl operation
5162306a36Sopenharmony_ci * @MMC_DRV_OP_IOCTL_RPMB: RPMB-oriented ioctl operation
5262306a36Sopenharmony_ci * @MMC_DRV_OP_BOOT_WP: write protect boot partitions
5362306a36Sopenharmony_ci * @MMC_DRV_OP_GET_CARD_STATUS: get card status
5462306a36Sopenharmony_ci * @MMC_DRV_OP_GET_EXT_CSD: get the EXT CSD from an eMMC card
5562306a36Sopenharmony_ci */
5662306a36Sopenharmony_cienum mmc_drv_op {
5762306a36Sopenharmony_ci	MMC_DRV_OP_IOCTL,
5862306a36Sopenharmony_ci	MMC_DRV_OP_IOCTL_RPMB,
5962306a36Sopenharmony_ci	MMC_DRV_OP_BOOT_WP,
6062306a36Sopenharmony_ci	MMC_DRV_OP_GET_CARD_STATUS,
6162306a36Sopenharmony_ci	MMC_DRV_OP_GET_EXT_CSD,
6262306a36Sopenharmony_ci};
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_cistruct mmc_queue_req {
6562306a36Sopenharmony_ci	struct mmc_blk_request	brq;
6662306a36Sopenharmony_ci	struct scatterlist	*sg;
6762306a36Sopenharmony_ci	enum mmc_drv_op		drv_op;
6862306a36Sopenharmony_ci	int			drv_op_result;
6962306a36Sopenharmony_ci	void			*drv_op_data;
7062306a36Sopenharmony_ci	unsigned int		ioc_count;
7162306a36Sopenharmony_ci	int			retries;
7262306a36Sopenharmony_ci};
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_cistruct mmc_queue {
7562306a36Sopenharmony_ci	struct mmc_card		*card;
7662306a36Sopenharmony_ci	struct mmc_ctx		ctx;
7762306a36Sopenharmony_ci	struct blk_mq_tag_set	tag_set;
7862306a36Sopenharmony_ci	struct mmc_blk_data	*blkdata;
7962306a36Sopenharmony_ci	struct request_queue	*queue;
8062306a36Sopenharmony_ci	spinlock_t		lock;
8162306a36Sopenharmony_ci	int			in_flight[MMC_ISSUE_MAX];
8262306a36Sopenharmony_ci	unsigned int		cqe_busy;
8362306a36Sopenharmony_ci#define MMC_CQE_DCMD_BUSY	BIT(0)
8462306a36Sopenharmony_ci	bool			busy;
8562306a36Sopenharmony_ci	bool			recovery_needed;
8662306a36Sopenharmony_ci	bool			in_recovery;
8762306a36Sopenharmony_ci	bool			rw_wait;
8862306a36Sopenharmony_ci	bool			waiting;
8962306a36Sopenharmony_ci	struct work_struct	recovery_work;
9062306a36Sopenharmony_ci	wait_queue_head_t	wait;
9162306a36Sopenharmony_ci	struct request		*recovery_req;
9262306a36Sopenharmony_ci	struct request		*complete_req;
9362306a36Sopenharmony_ci	struct mutex		complete_lock;
9462306a36Sopenharmony_ci	struct work_struct	complete_work;
9562306a36Sopenharmony_ci};
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_cistruct gendisk *mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card);
9862306a36Sopenharmony_ciextern void mmc_cleanup_queue(struct mmc_queue *);
9962306a36Sopenharmony_ciextern void mmc_queue_suspend(struct mmc_queue *);
10062306a36Sopenharmony_ciextern void mmc_queue_resume(struct mmc_queue *);
10162306a36Sopenharmony_ciextern unsigned int mmc_queue_map_sg(struct mmc_queue *,
10262306a36Sopenharmony_ci				     struct mmc_queue_req *);
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_civoid mmc_cqe_check_busy(struct mmc_queue *mq);
10562306a36Sopenharmony_civoid mmc_cqe_recovery_notifier(struct mmc_request *mrq);
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_cienum mmc_issue_type mmc_issue_type(struct mmc_queue *mq, struct request *req);
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_cistatic inline int mmc_tot_in_flight(struct mmc_queue *mq)
11062306a36Sopenharmony_ci{
11162306a36Sopenharmony_ci	return mq->in_flight[MMC_ISSUE_SYNC] +
11262306a36Sopenharmony_ci	       mq->in_flight[MMC_ISSUE_DCMD] +
11362306a36Sopenharmony_ci	       mq->in_flight[MMC_ISSUE_ASYNC];
11462306a36Sopenharmony_ci}
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_cistatic inline int mmc_cqe_qcnt(struct mmc_queue *mq)
11762306a36Sopenharmony_ci{
11862306a36Sopenharmony_ci	return mq->in_flight[MMC_ISSUE_DCMD] +
11962306a36Sopenharmony_ci	       mq->in_flight[MMC_ISSUE_ASYNC];
12062306a36Sopenharmony_ci}
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci#endif
123