162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#ifndef _ELEVATOR_H
362306a36Sopenharmony_ci#define _ELEVATOR_H
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#include <linux/percpu.h>
662306a36Sopenharmony_ci#include <linux/hashtable.h>
762306a36Sopenharmony_ci#include "blk-mq.h"
862306a36Sopenharmony_ci
962306a36Sopenharmony_cistruct io_cq;
1062306a36Sopenharmony_cistruct elevator_type;
1162306a36Sopenharmony_cistruct blk_mq_debugfs_attr;
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci/*
1462306a36Sopenharmony_ci * Return values from elevator merger
1562306a36Sopenharmony_ci */
1662306a36Sopenharmony_cienum elv_merge {
1762306a36Sopenharmony_ci	ELEVATOR_NO_MERGE	= 0,
1862306a36Sopenharmony_ci	ELEVATOR_FRONT_MERGE	= 1,
1962306a36Sopenharmony_ci	ELEVATOR_BACK_MERGE	= 2,
2062306a36Sopenharmony_ci	ELEVATOR_DISCARD_MERGE	= 3,
2162306a36Sopenharmony_ci};
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_cistruct blk_mq_alloc_data;
2462306a36Sopenharmony_cistruct blk_mq_hw_ctx;
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_cistruct elevator_mq_ops {
2762306a36Sopenharmony_ci	int (*init_sched)(struct request_queue *, struct elevator_type *);
2862306a36Sopenharmony_ci	void (*exit_sched)(struct elevator_queue *);
2962306a36Sopenharmony_ci	int (*init_hctx)(struct blk_mq_hw_ctx *, unsigned int);
3062306a36Sopenharmony_ci	void (*exit_hctx)(struct blk_mq_hw_ctx *, unsigned int);
3162306a36Sopenharmony_ci	void (*depth_updated)(struct blk_mq_hw_ctx *);
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci	bool (*allow_merge)(struct request_queue *, struct request *, struct bio *);
3462306a36Sopenharmony_ci	bool (*bio_merge)(struct request_queue *, struct bio *, unsigned int);
3562306a36Sopenharmony_ci	int (*request_merge)(struct request_queue *q, struct request **, struct bio *);
3662306a36Sopenharmony_ci	void (*request_merged)(struct request_queue *, struct request *, enum elv_merge);
3762306a36Sopenharmony_ci	void (*requests_merged)(struct request_queue *, struct request *, struct request *);
3862306a36Sopenharmony_ci	void (*limit_depth)(blk_opf_t, struct blk_mq_alloc_data *);
3962306a36Sopenharmony_ci	void (*prepare_request)(struct request *);
4062306a36Sopenharmony_ci	void (*finish_request)(struct request *);
4162306a36Sopenharmony_ci	void (*insert_requests)(struct blk_mq_hw_ctx *hctx, struct list_head *list,
4262306a36Sopenharmony_ci			blk_insert_t flags);
4362306a36Sopenharmony_ci	struct request *(*dispatch_request)(struct blk_mq_hw_ctx *);
4462306a36Sopenharmony_ci	bool (*has_work)(struct blk_mq_hw_ctx *);
4562306a36Sopenharmony_ci	void (*completed_request)(struct request *, u64);
4662306a36Sopenharmony_ci	void (*requeue_request)(struct request *);
4762306a36Sopenharmony_ci	struct request *(*former_request)(struct request_queue *, struct request *);
4862306a36Sopenharmony_ci	struct request *(*next_request)(struct request_queue *, struct request *);
4962306a36Sopenharmony_ci	void (*init_icq)(struct io_cq *);
5062306a36Sopenharmony_ci	void (*exit_icq)(struct io_cq *);
5162306a36Sopenharmony_ci};
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci#define ELV_NAME_MAX	(16)
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_cistruct elv_fs_entry {
5662306a36Sopenharmony_ci	struct attribute attr;
5762306a36Sopenharmony_ci	ssize_t (*show)(struct elevator_queue *, char *);
5862306a36Sopenharmony_ci	ssize_t (*store)(struct elevator_queue *, const char *, size_t);
5962306a36Sopenharmony_ci};
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci/*
6262306a36Sopenharmony_ci * identifies an elevator type, such as AS or deadline
6362306a36Sopenharmony_ci */
6462306a36Sopenharmony_cistruct elevator_type
6562306a36Sopenharmony_ci{
6662306a36Sopenharmony_ci	/* managed by elevator core */
6762306a36Sopenharmony_ci	struct kmem_cache *icq_cache;
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	/* fields provided by elevator implementation */
7062306a36Sopenharmony_ci	struct elevator_mq_ops ops;
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci	size_t icq_size;	/* see iocontext.h */
7362306a36Sopenharmony_ci	size_t icq_align;	/* ditto */
7462306a36Sopenharmony_ci	struct elv_fs_entry *elevator_attrs;
7562306a36Sopenharmony_ci	const char *elevator_name;
7662306a36Sopenharmony_ci	const char *elevator_alias;
7762306a36Sopenharmony_ci	const unsigned int elevator_features;
7862306a36Sopenharmony_ci	struct module *elevator_owner;
7962306a36Sopenharmony_ci#ifdef CONFIG_BLK_DEBUG_FS
8062306a36Sopenharmony_ci	const struct blk_mq_debugfs_attr *queue_debugfs_attrs;
8162306a36Sopenharmony_ci	const struct blk_mq_debugfs_attr *hctx_debugfs_attrs;
8262306a36Sopenharmony_ci#endif
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci	/* managed by elevator core */
8562306a36Sopenharmony_ci	char icq_cache_name[ELV_NAME_MAX + 6];	/* elvname + "_io_cq" */
8662306a36Sopenharmony_ci	struct list_head list;
8762306a36Sopenharmony_ci};
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_cistatic inline bool elevator_tryget(struct elevator_type *e)
9062306a36Sopenharmony_ci{
9162306a36Sopenharmony_ci	return try_module_get(e->elevator_owner);
9262306a36Sopenharmony_ci}
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_cistatic inline void __elevator_get(struct elevator_type *e)
9562306a36Sopenharmony_ci{
9662306a36Sopenharmony_ci	__module_get(e->elevator_owner);
9762306a36Sopenharmony_ci}
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_cistatic inline void elevator_put(struct elevator_type *e)
10062306a36Sopenharmony_ci{
10162306a36Sopenharmony_ci	module_put(e->elevator_owner);
10262306a36Sopenharmony_ci}
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci#define ELV_HASH_BITS 6
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_civoid elv_rqhash_del(struct request_queue *q, struct request *rq);
10762306a36Sopenharmony_civoid elv_rqhash_add(struct request_queue *q, struct request *rq);
10862306a36Sopenharmony_civoid elv_rqhash_reposition(struct request_queue *q, struct request *rq);
10962306a36Sopenharmony_cistruct request *elv_rqhash_find(struct request_queue *q, sector_t offset);
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci/*
11262306a36Sopenharmony_ci * each queue has an elevator_queue associated with it
11362306a36Sopenharmony_ci */
11462306a36Sopenharmony_cistruct elevator_queue
11562306a36Sopenharmony_ci{
11662306a36Sopenharmony_ci	struct elevator_type *type;
11762306a36Sopenharmony_ci	void *elevator_data;
11862306a36Sopenharmony_ci	struct kobject kobj;
11962306a36Sopenharmony_ci	struct mutex sysfs_lock;
12062306a36Sopenharmony_ci	unsigned long flags;
12162306a36Sopenharmony_ci	DECLARE_HASHTABLE(hash, ELV_HASH_BITS);
12262306a36Sopenharmony_ci};
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci#define ELEVATOR_FLAG_REGISTERED	0
12562306a36Sopenharmony_ci#define ELEVATOR_FLAG_DISABLE_WBT	1
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci/*
12862306a36Sopenharmony_ci * block elevator interface
12962306a36Sopenharmony_ci */
13062306a36Sopenharmony_ciextern enum elv_merge elv_merge(struct request_queue *, struct request **,
13162306a36Sopenharmony_ci		struct bio *);
13262306a36Sopenharmony_ciextern void elv_merge_requests(struct request_queue *, struct request *,
13362306a36Sopenharmony_ci			       struct request *);
13462306a36Sopenharmony_ciextern void elv_merged_request(struct request_queue *, struct request *,
13562306a36Sopenharmony_ci		enum elv_merge);
13662306a36Sopenharmony_ciextern bool elv_attempt_insert_merge(struct request_queue *, struct request *,
13762306a36Sopenharmony_ci				     struct list_head *);
13862306a36Sopenharmony_ciextern struct request *elv_former_request(struct request_queue *, struct request *);
13962306a36Sopenharmony_ciextern struct request *elv_latter_request(struct request_queue *, struct request *);
14062306a36Sopenharmony_civoid elevator_init_mq(struct request_queue *q);
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci/*
14362306a36Sopenharmony_ci * io scheduler registration
14462306a36Sopenharmony_ci */
14562306a36Sopenharmony_ciextern int elv_register(struct elevator_type *);
14662306a36Sopenharmony_ciextern void elv_unregister(struct elevator_type *);
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci/*
14962306a36Sopenharmony_ci * io scheduler sysfs switching
15062306a36Sopenharmony_ci */
15162306a36Sopenharmony_ciextern ssize_t elv_iosched_show(struct request_queue *, char *);
15262306a36Sopenharmony_ciextern ssize_t elv_iosched_store(struct request_queue *, const char *, size_t);
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ciextern bool elv_bio_merge_ok(struct request *, struct bio *);
15562306a36Sopenharmony_ciextern struct elevator_queue *elevator_alloc(struct request_queue *,
15662306a36Sopenharmony_ci					struct elevator_type *);
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_ci/*
15962306a36Sopenharmony_ci * Helper functions.
16062306a36Sopenharmony_ci */
16162306a36Sopenharmony_ciextern struct request *elv_rb_former_request(struct request_queue *, struct request *);
16262306a36Sopenharmony_ciextern struct request *elv_rb_latter_request(struct request_queue *, struct request *);
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci/*
16562306a36Sopenharmony_ci * rb support functions.
16662306a36Sopenharmony_ci */
16762306a36Sopenharmony_ciextern void elv_rb_add(struct rb_root *, struct request *);
16862306a36Sopenharmony_ciextern void elv_rb_del(struct rb_root *, struct request *);
16962306a36Sopenharmony_ciextern struct request *elv_rb_find(struct rb_root *, sector_t);
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci/*
17262306a36Sopenharmony_ci * Insertion selection
17362306a36Sopenharmony_ci */
17462306a36Sopenharmony_ci#define ELEVATOR_INSERT_FRONT	1
17562306a36Sopenharmony_ci#define ELEVATOR_INSERT_BACK	2
17662306a36Sopenharmony_ci#define ELEVATOR_INSERT_SORT	3
17762306a36Sopenharmony_ci#define ELEVATOR_INSERT_REQUEUE	4
17862306a36Sopenharmony_ci#define ELEVATOR_INSERT_FLUSH	5
17962306a36Sopenharmony_ci#define ELEVATOR_INSERT_SORT_MERGE	6
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci#define rb_entry_rq(node)	rb_entry((node), struct request, rb_node)
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci#define rq_entry_fifo(ptr)	list_entry((ptr), struct request, queuelist)
18462306a36Sopenharmony_ci#define rq_fifo_clear(rq)	list_del_init(&(rq)->queuelist)
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ci#endif /* _ELEVATOR_H */
187