| 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
| 2 | #ifndef MMC_QUEUE_H |
| 3 | #define MMC_QUEUE_H |
| 4 | |
| 5 | #include <linux/types.h> |
| 6 | #include <linux/blkdev.h> |
| 7 | #include <linux/blk-mq.h> |
| 8 | #include <linux/mmc/core.h> |
| 9 | #include <linux/mmc/host.h> |
| 10 | |
| 11 | enum mmc_issued { |
| 12 | MMC_REQ_STARTED, |
| 13 | MMC_REQ_BUSY, |
| 14 | MMC_REQ_FAILED_TO_START, |
| 15 | MMC_REQ_FINISHED, |
| 16 | }; |
| 17 | |
| 18 | enum mmc_issue_type { |
| 19 | MMC_ISSUE_SYNC, |
| 20 | MMC_ISSUE_DCMD, |
| 21 | MMC_ISSUE_ASYNC, |
| 22 | MMC_ISSUE_MAX, |
| 23 | }; |
| 24 | |
| 25 | static inline struct mmc_queue_req *req_to_mmc_queue_req(struct request *rq) |
| 26 | { |
| 27 | return blk_mq_rq_to_pdu(rq); |
| 28 | } |
| 29 | |
| 30 | struct mmc_queue_req; |
| 31 | |
| 32 | static inline struct request *mmc_queue_req_to_req(struct mmc_queue_req *mqr) |
| 33 | { |
| 34 | return blk_mq_rq_from_pdu(pdu: mqr); |
| 35 | } |
| 36 | |
| 37 | struct mmc_blk_data; |
| 38 | struct mmc_blk_ioc_data; |
| 39 | |
| 40 | struct mmc_blk_request { |
| 41 | struct mmc_request mrq; |
| 42 | struct mmc_command sbc; |
| 43 | struct mmc_command cmd; |
| 44 | struct mmc_command stop; |
| 45 | struct mmc_data data; |
| 46 | }; |
| 47 | |
| 48 | /** |
| 49 | * enum mmc_drv_op - enumerates the operations in the mmc_queue_req |
| 50 | * @MMC_DRV_OP_IOCTL: ioctl operation |
| 51 | * @MMC_DRV_OP_IOCTL_RPMB: RPMB-oriented ioctl operation |
| 52 | * @MMC_DRV_OP_BOOT_WP: write protect boot partitions |
| 53 | * @MMC_DRV_OP_GET_CARD_STATUS: get card status |
| 54 | * @MMC_DRV_OP_GET_EXT_CSD: get the EXT CSD from an eMMC card |
| 55 | */ |
| 56 | enum mmc_drv_op { |
| 57 | MMC_DRV_OP_IOCTL, |
| 58 | MMC_DRV_OP_IOCTL_RPMB, |
| 59 | MMC_DRV_OP_BOOT_WP, |
| 60 | MMC_DRV_OP_GET_CARD_STATUS, |
| 61 | MMC_DRV_OP_GET_EXT_CSD, |
| 62 | }; |
| 63 | |
| 64 | struct mmc_queue_req { |
| 65 | struct mmc_blk_request brq; |
| 66 | struct scatterlist *sg; |
| 67 | enum mmc_drv_op drv_op; |
| 68 | int drv_op_result; |
| 69 | void *drv_op_data; |
| 70 | unsigned int ioc_count; |
| 71 | int retries; |
| 72 | }; |
| 73 | |
| 74 | struct mmc_queue { |
| 75 | struct mmc_card *card; |
| 76 | struct mmc_ctx ctx; |
| 77 | struct blk_mq_tag_set tag_set; |
| 78 | struct mmc_blk_data *blkdata; |
| 79 | struct request_queue *queue; |
| 80 | spinlock_t lock; |
| 81 | int in_flight[MMC_ISSUE_MAX]; |
| 82 | unsigned int cqe_busy; |
| 83 | #define MMC_CQE_DCMD_BUSY BIT(0) |
| 84 | bool busy; |
| 85 | bool recovery_needed; |
| 86 | bool in_recovery; |
| 87 | bool rw_wait; |
| 88 | bool waiting; |
| 89 | struct work_struct recovery_work; |
| 90 | wait_queue_head_t wait; |
| 91 | struct request *recovery_req; |
| 92 | struct request *complete_req; |
| 93 | struct mutex complete_lock; |
| 94 | struct work_struct complete_work; |
| 95 | }; |
| 96 | |
| 97 | struct gendisk *mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, |
| 98 | unsigned int features); |
| 99 | extern void mmc_cleanup_queue(struct mmc_queue *); |
| 100 | extern void mmc_queue_suspend(struct mmc_queue *); |
| 101 | extern void mmc_queue_resume(struct mmc_queue *); |
| 102 | extern unsigned int mmc_queue_map_sg(struct mmc_queue *, |
| 103 | struct mmc_queue_req *); |
| 104 | |
| 105 | void mmc_cqe_check_busy(struct mmc_queue *mq); |
| 106 | void mmc_cqe_recovery_notifier(struct mmc_request *mrq); |
| 107 | |
| 108 | enum mmc_issue_type mmc_issue_type(struct mmc_queue *mq, struct request *req); |
| 109 | |
| 110 | static inline int mmc_tot_in_flight(struct mmc_queue *mq) |
| 111 | { |
| 112 | return mq->in_flight[MMC_ISSUE_SYNC] + |
| 113 | mq->in_flight[MMC_ISSUE_DCMD] + |
| 114 | mq->in_flight[MMC_ISSUE_ASYNC]; |
| 115 | } |
| 116 | |
| 117 | static inline int mmc_cqe_qcnt(struct mmc_queue *mq) |
| 118 | { |
| 119 | return mq->in_flight[MMC_ISSUE_DCMD] + |
| 120 | mq->in_flight[MMC_ISSUE_ASYNC]; |
| 121 | } |
| 122 | |
| 123 | #endif |
| 124 | |