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