1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
2bd166ef1SJens Axboe #ifndef BLK_MQ_SCHED_H
3bd166ef1SJens Axboe #define BLK_MQ_SCHED_H
4bd166ef1SJens Axboe
52e9bc346SChristoph Hellwig #include "elevator.h"
6bd166ef1SJens Axboe #include "blk-mq.h"
7bd166ef1SJens Axboe
8d2a27964SJohn Garry #define MAX_SCHED_RQ (16 * BLKDEV_DEFAULT_RQ)
9d97e594cSJohn Garry
10e4d750c9SJens Axboe bool blk_mq_sched_try_merge(struct request_queue *q, struct bio *bio,
1114ccb66bSChristoph Hellwig unsigned int nr_segs, struct request **merged_request);
12179ae84fSPavel Begunkov bool blk_mq_sched_bio_merge(struct request_queue *q, struct bio *bio,
1314ccb66bSChristoph Hellwig unsigned int nr_segs);
14fd2ef39cSJan Kara bool blk_mq_sched_try_insert_merge(struct request_queue *q, struct request *rq,
15fd2ef39cSJan Kara struct list_head *free);
167211aef8SDamien Le Moal void blk_mq_sched_mark_restart_hctx(struct blk_mq_hw_ctx *hctx);
17e9ea1596SPavel Begunkov void __blk_mq_sched_restart(struct blk_mq_hw_ctx *hctx);
18bd166ef1SJens Axboe
19bd166ef1SJens Axboe void blk_mq_sched_dispatch_requests(struct blk_mq_hw_ctx *hctx);
20bd166ef1SJens Axboe
21f5a6604fSNilay Shroff int blk_mq_init_sched(struct request_queue *q, struct elevator_type *e,
2204728ce9SNilay Shroff struct elevator_resources *res);
2354d5329dSOmar Sandoval void blk_mq_exit_sched(struct request_queue *q, struct elevator_queue *e);
241820f4f0SJohn Garry void blk_mq_sched_free_rqs(struct request_queue *q);
25bd166ef1SJens Axboe
26f5a6604fSNilay Shroff struct elevator_tags *blk_mq_alloc_sched_tags(struct blk_mq_tag_set *set,
276293e336SYu Kuai unsigned int nr_hw_queues, unsigned int nr_requests);
2804728ce9SNilay Shroff int blk_mq_alloc_sched_res(struct request_queue *q,
290315476eSNilay Shroff struct elevator_type *type,
300315476eSNilay Shroff struct elevator_resources *res,
310315476eSNilay Shroff unsigned int nr_hw_queues);
3204728ce9SNilay Shroff int blk_mq_alloc_sched_res_batch(struct xarray *elv_tbl,
3304225d13SNilay Shroff struct blk_mq_tag_set *set, unsigned int nr_hw_queues);
34232143b6SNilay Shroff int blk_mq_alloc_sched_ctx_batch(struct xarray *elv_tbl,
35232143b6SNilay Shroff struct blk_mq_tag_set *set);
36232143b6SNilay Shroff void blk_mq_free_sched_ctx_batch(struct xarray *elv_tbl);
37f5a6604fSNilay Shroff void blk_mq_free_sched_tags(struct elevator_tags *et,
38f5a6604fSNilay Shroff struct blk_mq_tag_set *set);
3904728ce9SNilay Shroff void blk_mq_free_sched_res(struct elevator_resources *res,
400315476eSNilay Shroff struct elevator_type *type,
4104728ce9SNilay Shroff struct blk_mq_tag_set *set);
4204728ce9SNilay Shroff void blk_mq_free_sched_res_batch(struct xarray *et_table,
4304225d13SNilay Shroff struct blk_mq_tag_set *set);
4461019afdSNilay Shroff /*
4561019afdSNilay Shroff * blk_mq_alloc_sched_data() - Allocates scheduler specific data
4661019afdSNilay Shroff * Returns:
4761019afdSNilay Shroff * - Pointer to allocated data on success
4861019afdSNilay Shroff * - NULL if no allocation needed
4961019afdSNilay Shroff * - ERR_PTR(-ENOMEM) in case of failure
5061019afdSNilay Shroff */
blk_mq_alloc_sched_data(struct request_queue * q,struct elevator_type * e)5161019afdSNilay Shroff static inline void *blk_mq_alloc_sched_data(struct request_queue *q,
5261019afdSNilay Shroff struct elevator_type *e)
5361019afdSNilay Shroff {
5461019afdSNilay Shroff void *sched_data;
5561019afdSNilay Shroff
5661019afdSNilay Shroff if (!e || !e->ops.alloc_sched_data)
5761019afdSNilay Shroff return NULL;
5861019afdSNilay Shroff
5961019afdSNilay Shroff sched_data = e->ops.alloc_sched_data(q);
6061019afdSNilay Shroff return (sched_data) ?: ERR_PTR(-ENOMEM);
6161019afdSNilay Shroff }
6261019afdSNilay Shroff
blk_mq_free_sched_data(struct elevator_type * e,void * data)6361019afdSNilay Shroff static inline void blk_mq_free_sched_data(struct elevator_type *e, void *data)
6461019afdSNilay Shroff {
6561019afdSNilay Shroff if (e && e->ops.free_sched_data)
6661019afdSNilay Shroff e->ops.free_sched_data(data);
6761019afdSNilay Shroff }
68f5a6604fSNilay Shroff
blk_mq_sched_restart(struct blk_mq_hw_ctx * hctx)69e9ea1596SPavel Begunkov static inline void blk_mq_sched_restart(struct blk_mq_hw_ctx *hctx)
70e9ea1596SPavel Begunkov {
71e9ea1596SPavel Begunkov if (test_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state))
72e9ea1596SPavel Begunkov __blk_mq_sched_restart(hctx);
73e9ea1596SPavel Begunkov }
74e9ea1596SPavel Begunkov
bio_mergeable(struct bio * bio)758addffd6SChristoph Hellwig static inline bool bio_mergeable(struct bio *bio)
768addffd6SChristoph Hellwig {
778addffd6SChristoph Hellwig return !(bio->bi_opf & REQ_NOMERGE_FLAGS);
788addffd6SChristoph Hellwig }
798addffd6SChristoph Hellwig
80bd166ef1SJens Axboe static inline bool
blk_mq_sched_allow_merge(struct request_queue * q,struct request * rq,struct bio * bio)81bd166ef1SJens Axboe blk_mq_sched_allow_merge(struct request_queue *q, struct request *rq,
82bd166ef1SJens Axboe struct bio *bio)
83bd166ef1SJens Axboe {
84dd6216bbSChristoph Hellwig if (rq->rq_flags & RQF_USE_SCHED) {
85bd166ef1SJens Axboe struct elevator_queue *e = q->elevator;
86bd166ef1SJens Axboe
872ff0682dSJens Axboe if (e->type->ops.allow_merge)
88f9cd4bfeSJens Axboe return e->type->ops.allow_merge(q, rq, bio);
892ff0682dSJens Axboe }
90bd166ef1SJens Axboe return true;
91bd166ef1SJens Axboe }
92bd166ef1SJens Axboe
blk_mq_sched_completed_request(struct request * rq,u64 now)93ed88660aSOmar Sandoval static inline void blk_mq_sched_completed_request(struct request *rq, u64 now)
94bd166ef1SJens Axboe {
95dd6216bbSChristoph Hellwig if (rq->rq_flags & RQF_USE_SCHED) {
96c05f8525SOmar Sandoval struct elevator_queue *e = rq->q->elevator;
97bd166ef1SJens Axboe
982ff0682dSJens Axboe if (e->type->ops.completed_request)
99f9cd4bfeSJens Axboe e->type->ops.completed_request(rq, now);
100bd166ef1SJens Axboe }
1012ff0682dSJens Axboe }
102bd166ef1SJens Axboe
blk_mq_sched_requeue_request(struct request * rq)103bd166ef1SJens Axboe static inline void blk_mq_sched_requeue_request(struct request *rq)
104bd166ef1SJens Axboe {
105dd6216bbSChristoph Hellwig if (rq->rq_flags & RQF_USE_SCHED) {
106bd166ef1SJens Axboe struct request_queue *q = rq->q;
107bd166ef1SJens Axboe struct elevator_queue *e = q->elevator;
108bd166ef1SJens Axboe
109fdcab6cdSChristoph Hellwig if (e->type->ops.requeue_request)
110f9cd4bfeSJens Axboe e->type->ops.requeue_request(rq);
111bd166ef1SJens Axboe }
1122ff0682dSJens Axboe }
113bd166ef1SJens Axboe
blk_mq_sched_has_work(struct blk_mq_hw_ctx * hctx)114bd166ef1SJens Axboe static inline bool blk_mq_sched_has_work(struct blk_mq_hw_ctx *hctx)
115bd166ef1SJens Axboe {
116bd166ef1SJens Axboe struct elevator_queue *e = hctx->queue->elevator;
117bd166ef1SJens Axboe
118f9cd4bfeSJens Axboe if (e && e->type->ops.has_work)
119f9cd4bfeSJens Axboe return e->type->ops.has_work(hctx);
120bd166ef1SJens Axboe
121bd166ef1SJens Axboe return false;
122bd166ef1SJens Axboe }
123bd166ef1SJens Axboe
blk_mq_sched_needs_restart(struct blk_mq_hw_ctx * hctx)124bd166ef1SJens Axboe static inline bool blk_mq_sched_needs_restart(struct blk_mq_hw_ctx *hctx)
125bd166ef1SJens Axboe {
126bd166ef1SJens Axboe return test_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state);
127bd166ef1SJens Axboe }
128bd166ef1SJens Axboe
blk_mq_set_min_shallow_depth(struct request_queue * q,unsigned int depth)1297d337eefSYu Kuai static inline void blk_mq_set_min_shallow_depth(struct request_queue *q,
1307d337eefSYu Kuai unsigned int depth)
1317d337eefSYu Kuai {
1327d337eefSYu Kuai struct blk_mq_hw_ctx *hctx;
1337d337eefSYu Kuai unsigned long i;
1347d337eefSYu Kuai
1357d337eefSYu Kuai queue_for_each_hw_ctx(q, hctx, i)
1367d337eefSYu Kuai sbitmap_queue_min_shallow_depth(&hctx->sched_tags->bitmap_tags,
1377d337eefSYu Kuai depth);
1387d337eefSYu Kuai }
1397d337eefSYu Kuai
blk_mq_is_sync_read(blk_opf_t opf)140*1db61b0aSYu Kuai static inline bool blk_mq_is_sync_read(blk_opf_t opf)
141*1db61b0aSYu Kuai {
142*1db61b0aSYu Kuai return op_is_sync(opf) && !op_is_write(opf);
143*1db61b0aSYu Kuai }
144*1db61b0aSYu Kuai
145bd166ef1SJens Axboe #endif
146