1320ae51fSJens Axboe #include <linux/kernel.h> 2320ae51fSJens Axboe #include <linux/module.h> 3320ae51fSJens Axboe #include <linux/backing-dev.h> 4320ae51fSJens Axboe #include <linux/bio.h> 5320ae51fSJens Axboe #include <linux/blkdev.h> 6320ae51fSJens Axboe #include <linux/mm.h> 7320ae51fSJens Axboe #include <linux/init.h> 8320ae51fSJens Axboe #include <linux/slab.h> 9320ae51fSJens Axboe #include <linux/workqueue.h> 10320ae51fSJens Axboe #include <linux/smp.h> 11320ae51fSJens Axboe 12320ae51fSJens Axboe #include <linux/blk-mq.h> 13320ae51fSJens Axboe #include "blk-mq.h" 14320ae51fSJens Axboe #include "blk-mq-tag.h" 15320ae51fSJens Axboe 16320ae51fSJens Axboe static void blk_mq_sysfs_release(struct kobject *kobj) 17320ae51fSJens Axboe { 18320ae51fSJens Axboe } 19320ae51fSJens Axboe 20320ae51fSJens Axboe struct blk_mq_ctx_sysfs_entry { 21320ae51fSJens Axboe struct attribute attr; 22320ae51fSJens Axboe ssize_t (*show)(struct blk_mq_ctx *, char *); 23320ae51fSJens Axboe ssize_t (*store)(struct blk_mq_ctx *, const char *, size_t); 24320ae51fSJens Axboe }; 25320ae51fSJens Axboe 26320ae51fSJens Axboe struct blk_mq_hw_ctx_sysfs_entry { 27320ae51fSJens Axboe struct attribute attr; 28320ae51fSJens Axboe ssize_t (*show)(struct blk_mq_hw_ctx *, char *); 29320ae51fSJens Axboe ssize_t (*store)(struct blk_mq_hw_ctx *, const char *, size_t); 30320ae51fSJens Axboe }; 31320ae51fSJens Axboe 32320ae51fSJens Axboe static ssize_t blk_mq_sysfs_show(struct kobject *kobj, struct attribute *attr, 33320ae51fSJens Axboe char *page) 34320ae51fSJens Axboe { 35320ae51fSJens Axboe struct blk_mq_ctx_sysfs_entry *entry; 36320ae51fSJens Axboe struct blk_mq_ctx *ctx; 37320ae51fSJens Axboe struct request_queue *q; 38320ae51fSJens Axboe ssize_t res; 39320ae51fSJens Axboe 40320ae51fSJens Axboe entry = container_of(attr, struct blk_mq_ctx_sysfs_entry, attr); 41320ae51fSJens Axboe ctx = container_of(kobj, struct blk_mq_ctx, kobj); 42320ae51fSJens Axboe q = ctx->queue; 43320ae51fSJens Axboe 44320ae51fSJens Axboe if (!entry->show) 45320ae51fSJens Axboe return -EIO; 46320ae51fSJens Axboe 47320ae51fSJens Axboe res = -ENOENT; 48320ae51fSJens Axboe mutex_lock(&q->sysfs_lock); 49320ae51fSJens Axboe if (!blk_queue_dying(q)) 50320ae51fSJens Axboe res = entry->show(ctx, page); 51320ae51fSJens Axboe mutex_unlock(&q->sysfs_lock); 52320ae51fSJens Axboe return res; 53320ae51fSJens Axboe } 54320ae51fSJens Axboe 55320ae51fSJens Axboe static ssize_t blk_mq_sysfs_store(struct kobject *kobj, struct attribute *attr, 56320ae51fSJens Axboe const char *page, size_t length) 57320ae51fSJens Axboe { 58320ae51fSJens Axboe struct blk_mq_ctx_sysfs_entry *entry; 59320ae51fSJens Axboe struct blk_mq_ctx *ctx; 60320ae51fSJens Axboe struct request_queue *q; 61320ae51fSJens Axboe ssize_t res; 62320ae51fSJens Axboe 63320ae51fSJens Axboe entry = container_of(attr, struct blk_mq_ctx_sysfs_entry, attr); 64320ae51fSJens Axboe ctx = container_of(kobj, struct blk_mq_ctx, kobj); 65320ae51fSJens Axboe q = ctx->queue; 66320ae51fSJens Axboe 67320ae51fSJens Axboe if (!entry->store) 68320ae51fSJens Axboe return -EIO; 69320ae51fSJens Axboe 70320ae51fSJens Axboe res = -ENOENT; 71320ae51fSJens Axboe mutex_lock(&q->sysfs_lock); 72320ae51fSJens Axboe if (!blk_queue_dying(q)) 73320ae51fSJens Axboe res = entry->store(ctx, page, length); 74320ae51fSJens Axboe mutex_unlock(&q->sysfs_lock); 75320ae51fSJens Axboe return res; 76320ae51fSJens Axboe } 77320ae51fSJens Axboe 78320ae51fSJens Axboe static ssize_t blk_mq_hw_sysfs_show(struct kobject *kobj, 79320ae51fSJens Axboe struct attribute *attr, char *page) 80320ae51fSJens Axboe { 81320ae51fSJens Axboe struct blk_mq_hw_ctx_sysfs_entry *entry; 82320ae51fSJens Axboe struct blk_mq_hw_ctx *hctx; 83320ae51fSJens Axboe struct request_queue *q; 84320ae51fSJens Axboe ssize_t res; 85320ae51fSJens Axboe 86320ae51fSJens Axboe entry = container_of(attr, struct blk_mq_hw_ctx_sysfs_entry, attr); 87320ae51fSJens Axboe hctx = container_of(kobj, struct blk_mq_hw_ctx, kobj); 88320ae51fSJens Axboe q = hctx->queue; 89320ae51fSJens Axboe 90320ae51fSJens Axboe if (!entry->show) 91320ae51fSJens Axboe return -EIO; 92320ae51fSJens Axboe 93320ae51fSJens Axboe res = -ENOENT; 94320ae51fSJens Axboe mutex_lock(&q->sysfs_lock); 95320ae51fSJens Axboe if (!blk_queue_dying(q)) 96320ae51fSJens Axboe res = entry->show(hctx, page); 97320ae51fSJens Axboe mutex_unlock(&q->sysfs_lock); 98320ae51fSJens Axboe return res; 99320ae51fSJens Axboe } 100320ae51fSJens Axboe 101320ae51fSJens Axboe static ssize_t blk_mq_hw_sysfs_store(struct kobject *kobj, 102320ae51fSJens Axboe struct attribute *attr, const char *page, 103320ae51fSJens Axboe size_t length) 104320ae51fSJens Axboe { 105320ae51fSJens Axboe struct blk_mq_hw_ctx_sysfs_entry *entry; 106320ae51fSJens Axboe struct blk_mq_hw_ctx *hctx; 107320ae51fSJens Axboe struct request_queue *q; 108320ae51fSJens Axboe ssize_t res; 109320ae51fSJens Axboe 110320ae51fSJens Axboe entry = container_of(attr, struct blk_mq_hw_ctx_sysfs_entry, attr); 111320ae51fSJens Axboe hctx = container_of(kobj, struct blk_mq_hw_ctx, kobj); 112320ae51fSJens Axboe q = hctx->queue; 113320ae51fSJens Axboe 114320ae51fSJens Axboe if (!entry->store) 115320ae51fSJens Axboe return -EIO; 116320ae51fSJens Axboe 117320ae51fSJens Axboe res = -ENOENT; 118320ae51fSJens Axboe mutex_lock(&q->sysfs_lock); 119320ae51fSJens Axboe if (!blk_queue_dying(q)) 120320ae51fSJens Axboe res = entry->store(hctx, page, length); 121320ae51fSJens Axboe mutex_unlock(&q->sysfs_lock); 122320ae51fSJens Axboe return res; 123320ae51fSJens Axboe } 124320ae51fSJens Axboe 125320ae51fSJens Axboe static ssize_t blk_mq_sysfs_dispatched_show(struct blk_mq_ctx *ctx, char *page) 126320ae51fSJens Axboe { 127320ae51fSJens Axboe return sprintf(page, "%lu %lu\n", ctx->rq_dispatched[1], 128320ae51fSJens Axboe ctx->rq_dispatched[0]); 129320ae51fSJens Axboe } 130320ae51fSJens Axboe 131320ae51fSJens Axboe static ssize_t blk_mq_sysfs_merged_show(struct blk_mq_ctx *ctx, char *page) 132320ae51fSJens Axboe { 133320ae51fSJens Axboe return sprintf(page, "%lu\n", ctx->rq_merged); 134320ae51fSJens Axboe } 135320ae51fSJens Axboe 136320ae51fSJens Axboe static ssize_t blk_mq_sysfs_completed_show(struct blk_mq_ctx *ctx, char *page) 137320ae51fSJens Axboe { 138320ae51fSJens Axboe return sprintf(page, "%lu %lu\n", ctx->rq_completed[1], 139320ae51fSJens Axboe ctx->rq_completed[0]); 140320ae51fSJens Axboe } 141320ae51fSJens Axboe 142320ae51fSJens Axboe static ssize_t sysfs_list_show(char *page, struct list_head *list, char *msg) 143320ae51fSJens Axboe { 144320ae51fSJens Axboe struct request *rq; 145596f5aadSMing Lei int len = snprintf(page, PAGE_SIZE - 1, "%s:\n", msg); 146320ae51fSJens Axboe 147596f5aadSMing Lei list_for_each_entry(rq, list, queuelist) { 148596f5aadSMing Lei const int rq_len = 2 * sizeof(rq) + 2; 149320ae51fSJens Axboe 150596f5aadSMing Lei /* if the output will be truncated */ 151596f5aadSMing Lei if (PAGE_SIZE - 1 < len + rq_len) { 152596f5aadSMing Lei /* backspacing if it can't hold '\t...\n' */ 153596f5aadSMing Lei if (PAGE_SIZE - 1 < len + 5) 154596f5aadSMing Lei len -= rq_len; 155596f5aadSMing Lei len += snprintf(page + len, PAGE_SIZE - 1 - len, 156596f5aadSMing Lei "\t...\n"); 157596f5aadSMing Lei break; 158596f5aadSMing Lei } 159596f5aadSMing Lei len += snprintf(page + len, PAGE_SIZE - 1 - len, 160596f5aadSMing Lei "\t%p\n", rq); 161596f5aadSMing Lei } 162320ae51fSJens Axboe 163596f5aadSMing Lei return len; 164320ae51fSJens Axboe } 165320ae51fSJens Axboe 166320ae51fSJens Axboe static ssize_t blk_mq_sysfs_rq_list_show(struct blk_mq_ctx *ctx, char *page) 167320ae51fSJens Axboe { 168320ae51fSJens Axboe ssize_t ret; 169320ae51fSJens Axboe 170320ae51fSJens Axboe spin_lock(&ctx->lock); 171320ae51fSJens Axboe ret = sysfs_list_show(page, &ctx->rq_list, "CTX pending"); 172320ae51fSJens Axboe spin_unlock(&ctx->lock); 173320ae51fSJens Axboe 174320ae51fSJens Axboe return ret; 175320ae51fSJens Axboe } 176320ae51fSJens Axboe 17705229beeSJens Axboe static ssize_t blk_mq_hw_sysfs_poll_show(struct blk_mq_hw_ctx *hctx, char *page) 17805229beeSJens Axboe { 17905229beeSJens Axboe return sprintf(page, "invoked=%lu, success=%lu\n", hctx->poll_invoked, hctx->poll_success); 18005229beeSJens Axboe } 18105229beeSJens Axboe 182320ae51fSJens Axboe static ssize_t blk_mq_hw_sysfs_queued_show(struct blk_mq_hw_ctx *hctx, 183320ae51fSJens Axboe char *page) 184320ae51fSJens Axboe { 185320ae51fSJens Axboe return sprintf(page, "%lu\n", hctx->queued); 186320ae51fSJens Axboe } 187320ae51fSJens Axboe 188320ae51fSJens Axboe static ssize_t blk_mq_hw_sysfs_run_show(struct blk_mq_hw_ctx *hctx, char *page) 189320ae51fSJens Axboe { 190320ae51fSJens Axboe return sprintf(page, "%lu\n", hctx->run); 191320ae51fSJens Axboe } 192320ae51fSJens Axboe 193320ae51fSJens Axboe static ssize_t blk_mq_hw_sysfs_dispatched_show(struct blk_mq_hw_ctx *hctx, 194320ae51fSJens Axboe char *page) 195320ae51fSJens Axboe { 196320ae51fSJens Axboe char *start_page = page; 197320ae51fSJens Axboe int i; 198320ae51fSJens Axboe 199320ae51fSJens Axboe page += sprintf(page, "%8u\t%lu\n", 0U, hctx->dispatched[0]); 200320ae51fSJens Axboe 201320ae51fSJens Axboe for (i = 1; i < BLK_MQ_MAX_DISPATCH_ORDER; i++) { 202320ae51fSJens Axboe unsigned long d = 1U << (i - 1); 203320ae51fSJens Axboe 204320ae51fSJens Axboe page += sprintf(page, "%8lu\t%lu\n", d, hctx->dispatched[i]); 205320ae51fSJens Axboe } 206320ae51fSJens Axboe 207320ae51fSJens Axboe return page - start_page; 208320ae51fSJens Axboe } 209320ae51fSJens Axboe 210320ae51fSJens Axboe static ssize_t blk_mq_hw_sysfs_rq_list_show(struct blk_mq_hw_ctx *hctx, 211320ae51fSJens Axboe char *page) 212320ae51fSJens Axboe { 213320ae51fSJens Axboe ssize_t ret; 214320ae51fSJens Axboe 215320ae51fSJens Axboe spin_lock(&hctx->lock); 216320ae51fSJens Axboe ret = sysfs_list_show(page, &hctx->dispatch, "HCTX pending"); 217320ae51fSJens Axboe spin_unlock(&hctx->lock); 218320ae51fSJens Axboe 219320ae51fSJens Axboe return ret; 220320ae51fSJens Axboe } 221320ae51fSJens Axboe 222320ae51fSJens Axboe static ssize_t blk_mq_hw_sysfs_tags_show(struct blk_mq_hw_ctx *hctx, char *page) 223320ae51fSJens Axboe { 224320ae51fSJens Axboe return blk_mq_tag_sysfs_show(hctx->tags, page); 225320ae51fSJens Axboe } 226320ae51fSJens Axboe 2270d2602caSJens Axboe static ssize_t blk_mq_hw_sysfs_active_show(struct blk_mq_hw_ctx *hctx, char *page) 2280d2602caSJens Axboe { 2290d2602caSJens Axboe return sprintf(page, "%u\n", atomic_read(&hctx->nr_active)); 2300d2602caSJens Axboe } 2310d2602caSJens Axboe 232676141e4SJens Axboe static ssize_t blk_mq_hw_sysfs_cpus_show(struct blk_mq_hw_ctx *hctx, char *page) 233676141e4SJens Axboe { 234cb2da43eSJens Axboe unsigned int i, first = 1; 235676141e4SJens Axboe ssize_t ret = 0; 236676141e4SJens Axboe 237cb2da43eSJens Axboe for_each_cpu(i, hctx->cpumask) { 238676141e4SJens Axboe if (first) 239676141e4SJens Axboe ret += sprintf(ret + page, "%u", i); 240676141e4SJens Axboe else 241676141e4SJens Axboe ret += sprintf(ret + page, ", %u", i); 242676141e4SJens Axboe 243676141e4SJens Axboe first = 0; 244676141e4SJens Axboe } 245676141e4SJens Axboe 246676141e4SJens Axboe ret += sprintf(ret + page, "\n"); 247676141e4SJens Axboe return ret; 248676141e4SJens Axboe } 249676141e4SJens Axboe 250320ae51fSJens Axboe static struct blk_mq_ctx_sysfs_entry blk_mq_sysfs_dispatched = { 251320ae51fSJens Axboe .attr = {.name = "dispatched", .mode = S_IRUGO }, 252320ae51fSJens Axboe .show = blk_mq_sysfs_dispatched_show, 253320ae51fSJens Axboe }; 254320ae51fSJens Axboe static struct blk_mq_ctx_sysfs_entry blk_mq_sysfs_merged = { 255320ae51fSJens Axboe .attr = {.name = "merged", .mode = S_IRUGO }, 256320ae51fSJens Axboe .show = blk_mq_sysfs_merged_show, 257320ae51fSJens Axboe }; 258320ae51fSJens Axboe static struct blk_mq_ctx_sysfs_entry blk_mq_sysfs_completed = { 259320ae51fSJens Axboe .attr = {.name = "completed", .mode = S_IRUGO }, 260320ae51fSJens Axboe .show = blk_mq_sysfs_completed_show, 261320ae51fSJens Axboe }; 262320ae51fSJens Axboe static struct blk_mq_ctx_sysfs_entry blk_mq_sysfs_rq_list = { 263320ae51fSJens Axboe .attr = {.name = "rq_list", .mode = S_IRUGO }, 264320ae51fSJens Axboe .show = blk_mq_sysfs_rq_list_show, 265320ae51fSJens Axboe }; 266320ae51fSJens Axboe 267320ae51fSJens Axboe static struct attribute *default_ctx_attrs[] = { 268320ae51fSJens Axboe &blk_mq_sysfs_dispatched.attr, 269320ae51fSJens Axboe &blk_mq_sysfs_merged.attr, 270320ae51fSJens Axboe &blk_mq_sysfs_completed.attr, 271320ae51fSJens Axboe &blk_mq_sysfs_rq_list.attr, 272320ae51fSJens Axboe NULL, 273320ae51fSJens Axboe }; 274320ae51fSJens Axboe 275320ae51fSJens Axboe static struct blk_mq_hw_ctx_sysfs_entry blk_mq_hw_sysfs_queued = { 276320ae51fSJens Axboe .attr = {.name = "queued", .mode = S_IRUGO }, 277320ae51fSJens Axboe .show = blk_mq_hw_sysfs_queued_show, 278320ae51fSJens Axboe }; 279320ae51fSJens Axboe static struct blk_mq_hw_ctx_sysfs_entry blk_mq_hw_sysfs_run = { 280320ae51fSJens Axboe .attr = {.name = "run", .mode = S_IRUGO }, 281320ae51fSJens Axboe .show = blk_mq_hw_sysfs_run_show, 282320ae51fSJens Axboe }; 283320ae51fSJens Axboe static struct blk_mq_hw_ctx_sysfs_entry blk_mq_hw_sysfs_dispatched = { 284320ae51fSJens Axboe .attr = {.name = "dispatched", .mode = S_IRUGO }, 285320ae51fSJens Axboe .show = blk_mq_hw_sysfs_dispatched_show, 286320ae51fSJens Axboe }; 2870d2602caSJens Axboe static struct blk_mq_hw_ctx_sysfs_entry blk_mq_hw_sysfs_active = { 2880d2602caSJens Axboe .attr = {.name = "active", .mode = S_IRUGO }, 2890d2602caSJens Axboe .show = blk_mq_hw_sysfs_active_show, 2900d2602caSJens Axboe }; 291320ae51fSJens Axboe static struct blk_mq_hw_ctx_sysfs_entry blk_mq_hw_sysfs_pending = { 292320ae51fSJens Axboe .attr = {.name = "pending", .mode = S_IRUGO }, 293320ae51fSJens Axboe .show = blk_mq_hw_sysfs_rq_list_show, 294320ae51fSJens Axboe }; 295320ae51fSJens Axboe static struct blk_mq_hw_ctx_sysfs_entry blk_mq_hw_sysfs_tags = { 296320ae51fSJens Axboe .attr = {.name = "tags", .mode = S_IRUGO }, 297320ae51fSJens Axboe .show = blk_mq_hw_sysfs_tags_show, 298320ae51fSJens Axboe }; 299676141e4SJens Axboe static struct blk_mq_hw_ctx_sysfs_entry blk_mq_hw_sysfs_cpus = { 300676141e4SJens Axboe .attr = {.name = "cpu_list", .mode = S_IRUGO }, 301676141e4SJens Axboe .show = blk_mq_hw_sysfs_cpus_show, 302676141e4SJens Axboe }; 30305229beeSJens Axboe static struct blk_mq_hw_ctx_sysfs_entry blk_mq_hw_sysfs_poll = { 30405229beeSJens Axboe .attr = {.name = "io_poll", .mode = S_IRUGO }, 30505229beeSJens Axboe .show = blk_mq_hw_sysfs_poll_show, 30605229beeSJens Axboe }; 307320ae51fSJens Axboe 308320ae51fSJens Axboe static struct attribute *default_hw_ctx_attrs[] = { 309320ae51fSJens Axboe &blk_mq_hw_sysfs_queued.attr, 310320ae51fSJens Axboe &blk_mq_hw_sysfs_run.attr, 311320ae51fSJens Axboe &blk_mq_hw_sysfs_dispatched.attr, 312320ae51fSJens Axboe &blk_mq_hw_sysfs_pending.attr, 313320ae51fSJens Axboe &blk_mq_hw_sysfs_tags.attr, 314676141e4SJens Axboe &blk_mq_hw_sysfs_cpus.attr, 3150d2602caSJens Axboe &blk_mq_hw_sysfs_active.attr, 31605229beeSJens Axboe &blk_mq_hw_sysfs_poll.attr, 317320ae51fSJens Axboe NULL, 318320ae51fSJens Axboe }; 319320ae51fSJens Axboe 320320ae51fSJens Axboe static const struct sysfs_ops blk_mq_sysfs_ops = { 321320ae51fSJens Axboe .show = blk_mq_sysfs_show, 322320ae51fSJens Axboe .store = blk_mq_sysfs_store, 323320ae51fSJens Axboe }; 324320ae51fSJens Axboe 325320ae51fSJens Axboe static const struct sysfs_ops blk_mq_hw_sysfs_ops = { 326320ae51fSJens Axboe .show = blk_mq_hw_sysfs_show, 327320ae51fSJens Axboe .store = blk_mq_hw_sysfs_store, 328320ae51fSJens Axboe }; 329320ae51fSJens Axboe 330320ae51fSJens Axboe static struct kobj_type blk_mq_ktype = { 331320ae51fSJens Axboe .sysfs_ops = &blk_mq_sysfs_ops, 332320ae51fSJens Axboe .release = blk_mq_sysfs_release, 333320ae51fSJens Axboe }; 334320ae51fSJens Axboe 335320ae51fSJens Axboe static struct kobj_type blk_mq_ctx_ktype = { 336320ae51fSJens Axboe .sysfs_ops = &blk_mq_sysfs_ops, 337320ae51fSJens Axboe .default_attrs = default_ctx_attrs, 33874170118SMing Lei .release = blk_mq_sysfs_release, 339320ae51fSJens Axboe }; 340320ae51fSJens Axboe 341320ae51fSJens Axboe static struct kobj_type blk_mq_hw_ktype = { 342320ae51fSJens Axboe .sysfs_ops = &blk_mq_hw_sysfs_ops, 343320ae51fSJens Axboe .default_attrs = default_hw_ctx_attrs, 34474170118SMing Lei .release = blk_mq_sysfs_release, 345320ae51fSJens Axboe }; 346320ae51fSJens Axboe 347ee3c5db0SFengguang Wu static void blk_mq_unregister_hctx(struct blk_mq_hw_ctx *hctx) 34867aec14cSJens Axboe { 34967aec14cSJens Axboe struct blk_mq_ctx *ctx; 35067aec14cSJens Axboe int i; 35167aec14cSJens Axboe 3524593fdbeSAkinobu Mita if (!hctx->nr_ctx) 35367aec14cSJens Axboe return; 35467aec14cSJens Axboe 35567aec14cSJens Axboe hctx_for_each_ctx(hctx, ctx, i) 35667aec14cSJens Axboe kobject_del(&ctx->kobj); 35767aec14cSJens Axboe 35867aec14cSJens Axboe kobject_del(&hctx->kobj); 35967aec14cSJens Axboe } 36067aec14cSJens Axboe 361ee3c5db0SFengguang Wu static int blk_mq_register_hctx(struct blk_mq_hw_ctx *hctx) 36267aec14cSJens Axboe { 36367aec14cSJens Axboe struct request_queue *q = hctx->queue; 36467aec14cSJens Axboe struct blk_mq_ctx *ctx; 36567aec14cSJens Axboe int i, ret; 36667aec14cSJens Axboe 3674593fdbeSAkinobu Mita if (!hctx->nr_ctx) 36867aec14cSJens Axboe return 0; 36967aec14cSJens Axboe 37067aec14cSJens Axboe ret = kobject_add(&hctx->kobj, &q->mq_kobj, "%u", hctx->queue_num); 37167aec14cSJens Axboe if (ret) 37267aec14cSJens Axboe return ret; 37367aec14cSJens Axboe 37467aec14cSJens Axboe hctx_for_each_ctx(hctx, ctx, i) { 37567aec14cSJens Axboe ret = kobject_add(&ctx->kobj, &hctx->kobj, "cpu%u", ctx->cpu); 37667aec14cSJens Axboe if (ret) 37767aec14cSJens Axboe break; 37867aec14cSJens Axboe } 37967aec14cSJens Axboe 38067aec14cSJens Axboe return ret; 38167aec14cSJens Axboe } 38267aec14cSJens Axboe 383320ae51fSJens Axboe void blk_mq_unregister_disk(struct gendisk *disk) 384320ae51fSJens Axboe { 385320ae51fSJens Axboe struct request_queue *q = disk->queue; 38685157366SAndrey Vagin struct blk_mq_hw_ctx *hctx; 38785157366SAndrey Vagin struct blk_mq_ctx *ctx; 38885157366SAndrey Vagin int i, j; 38985157366SAndrey Vagin 3904593fdbeSAkinobu Mita blk_mq_disable_hotplug(); 3914593fdbeSAkinobu Mita 39285157366SAndrey Vagin queue_for_each_hw_ctx(q, hctx, i) { 39367aec14cSJens Axboe blk_mq_unregister_hctx(hctx); 39467aec14cSJens Axboe 39567aec14cSJens Axboe hctx_for_each_ctx(hctx, ctx, j) 39685157366SAndrey Vagin kobject_put(&ctx->kobj); 39767aec14cSJens Axboe 39885157366SAndrey Vagin kobject_put(&hctx->kobj); 39985157366SAndrey Vagin } 400320ae51fSJens Axboe 401320ae51fSJens Axboe kobject_uevent(&q->mq_kobj, KOBJ_REMOVE); 402320ae51fSJens Axboe kobject_del(&q->mq_kobj); 40385157366SAndrey Vagin kobject_put(&q->mq_kobj); 404320ae51fSJens Axboe 405320ae51fSJens Axboe kobject_put(&disk_to_dev(disk)->kobj); 4064593fdbeSAkinobu Mita 4074593fdbeSAkinobu Mita q->mq_sysfs_init_done = false; 4084593fdbeSAkinobu Mita blk_mq_enable_hotplug(); 409320ae51fSJens Axboe } 410320ae51fSJens Axboe 41167aec14cSJens Axboe static void blk_mq_sysfs_init(struct request_queue *q) 41267aec14cSJens Axboe { 41367aec14cSJens Axboe struct blk_mq_hw_ctx *hctx; 41467aec14cSJens Axboe struct blk_mq_ctx *ctx; 41506a41a99STakashi Iwai int i; 41667aec14cSJens Axboe 41767aec14cSJens Axboe kobject_init(&q->mq_kobj, &blk_mq_ktype); 41867aec14cSJens Axboe 41906a41a99STakashi Iwai queue_for_each_hw_ctx(q, hctx, i) 42067aec14cSJens Axboe kobject_init(&hctx->kobj, &blk_mq_hw_ktype); 42167aec14cSJens Axboe 42206a41a99STakashi Iwai queue_for_each_ctx(q, ctx, i) 42367aec14cSJens Axboe kobject_init(&ctx->kobj, &blk_mq_ctx_ktype); 42467aec14cSJens Axboe } 42567aec14cSJens Axboe 426320ae51fSJens Axboe int blk_mq_register_disk(struct gendisk *disk) 427320ae51fSJens Axboe { 428320ae51fSJens Axboe struct device *dev = disk_to_dev(disk); 429320ae51fSJens Axboe struct request_queue *q = disk->queue; 430320ae51fSJens Axboe struct blk_mq_hw_ctx *hctx; 43167aec14cSJens Axboe int ret, i; 432320ae51fSJens Axboe 4334593fdbeSAkinobu Mita blk_mq_disable_hotplug(); 4344593fdbeSAkinobu Mita 43567aec14cSJens Axboe blk_mq_sysfs_init(q); 436320ae51fSJens Axboe 437320ae51fSJens Axboe ret = kobject_add(&q->mq_kobj, kobject_get(&dev->kobj), "%s", "mq"); 438320ae51fSJens Axboe if (ret < 0) 4394593fdbeSAkinobu Mita goto out; 440320ae51fSJens Axboe 441320ae51fSJens Axboe kobject_uevent(&q->mq_kobj, KOBJ_ADD); 442320ae51fSJens Axboe 443320ae51fSJens Axboe queue_for_each_hw_ctx(q, hctx, i) { 44467aec14cSJens Axboe ret = blk_mq_register_hctx(hctx); 445320ae51fSJens Axboe if (ret) 446320ae51fSJens Axboe break; 447320ae51fSJens Axboe } 448320ae51fSJens Axboe 4494593fdbeSAkinobu Mita if (ret) 450320ae51fSJens Axboe blk_mq_unregister_disk(disk); 4514593fdbeSAkinobu Mita else 4524593fdbeSAkinobu Mita q->mq_sysfs_init_done = true; 4534593fdbeSAkinobu Mita out: 4544593fdbeSAkinobu Mita blk_mq_enable_hotplug(); 455320ae51fSJens Axboe 4564593fdbeSAkinobu Mita return ret; 457320ae51fSJens Axboe } 458b62c21b7SMike Snitzer EXPORT_SYMBOL_GPL(blk_mq_register_disk); 45967aec14cSJens Axboe 46067aec14cSJens Axboe void blk_mq_sysfs_unregister(struct request_queue *q) 46167aec14cSJens Axboe { 46267aec14cSJens Axboe struct blk_mq_hw_ctx *hctx; 46367aec14cSJens Axboe int i; 46467aec14cSJens Axboe 4654593fdbeSAkinobu Mita if (!q->mq_sysfs_init_done) 4664593fdbeSAkinobu Mita return; 4674593fdbeSAkinobu Mita 46867aec14cSJens Axboe queue_for_each_hw_ctx(q, hctx, i) 46967aec14cSJens Axboe blk_mq_unregister_hctx(hctx); 47067aec14cSJens Axboe } 47167aec14cSJens Axboe 47267aec14cSJens Axboe int blk_mq_sysfs_register(struct request_queue *q) 47367aec14cSJens Axboe { 47467aec14cSJens Axboe struct blk_mq_hw_ctx *hctx; 47567aec14cSJens Axboe int i, ret = 0; 47667aec14cSJens Axboe 4774593fdbeSAkinobu Mita if (!q->mq_sysfs_init_done) 4784593fdbeSAkinobu Mita return ret; 4794593fdbeSAkinobu Mita 48067aec14cSJens Axboe queue_for_each_hw_ctx(q, hctx, i) { 48167aec14cSJens Axboe ret = blk_mq_register_hctx(hctx); 48267aec14cSJens Axboe if (ret) 48367aec14cSJens Axboe break; 48467aec14cSJens Axboe } 48567aec14cSJens Axboe 48667aec14cSJens Axboe return ret; 48767aec14cSJens Axboe } 488