xref: /linux/block/blk-mq-sysfs.c (revision 8515736604941334bd9e8fc01edea685a228acd5)
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 	char *start_page = page;
145320ae51fSJens Axboe 	struct request *rq;
146320ae51fSJens Axboe 
147320ae51fSJens Axboe 	page += sprintf(page, "%s:\n", msg);
148320ae51fSJens Axboe 
149320ae51fSJens Axboe 	list_for_each_entry(rq, list, queuelist)
150320ae51fSJens Axboe 		page += sprintf(page, "\t%p\n", rq);
151320ae51fSJens Axboe 
152320ae51fSJens Axboe 	return page - start_page;
153320ae51fSJens Axboe }
154320ae51fSJens Axboe 
155320ae51fSJens Axboe static ssize_t blk_mq_sysfs_rq_list_show(struct blk_mq_ctx *ctx, char *page)
156320ae51fSJens Axboe {
157320ae51fSJens Axboe 	ssize_t ret;
158320ae51fSJens Axboe 
159320ae51fSJens Axboe 	spin_lock(&ctx->lock);
160320ae51fSJens Axboe 	ret = sysfs_list_show(page, &ctx->rq_list, "CTX pending");
161320ae51fSJens Axboe 	spin_unlock(&ctx->lock);
162320ae51fSJens Axboe 
163320ae51fSJens Axboe 	return ret;
164320ae51fSJens Axboe }
165320ae51fSJens Axboe 
166320ae51fSJens Axboe static ssize_t blk_mq_hw_sysfs_queued_show(struct blk_mq_hw_ctx *hctx,
167320ae51fSJens Axboe 					   char *page)
168320ae51fSJens Axboe {
169320ae51fSJens Axboe 	return sprintf(page, "%lu\n", hctx->queued);
170320ae51fSJens Axboe }
171320ae51fSJens Axboe 
172320ae51fSJens Axboe static ssize_t blk_mq_hw_sysfs_run_show(struct blk_mq_hw_ctx *hctx, char *page)
173320ae51fSJens Axboe {
174320ae51fSJens Axboe 	return sprintf(page, "%lu\n", hctx->run);
175320ae51fSJens Axboe }
176320ae51fSJens Axboe 
177320ae51fSJens Axboe static ssize_t blk_mq_hw_sysfs_dispatched_show(struct blk_mq_hw_ctx *hctx,
178320ae51fSJens Axboe 					       char *page)
179320ae51fSJens Axboe {
180320ae51fSJens Axboe 	char *start_page = page;
181320ae51fSJens Axboe 	int i;
182320ae51fSJens Axboe 
183320ae51fSJens Axboe 	page += sprintf(page, "%8u\t%lu\n", 0U, hctx->dispatched[0]);
184320ae51fSJens Axboe 
185320ae51fSJens Axboe 	for (i = 1; i < BLK_MQ_MAX_DISPATCH_ORDER; i++) {
186320ae51fSJens Axboe 		unsigned long d = 1U << (i - 1);
187320ae51fSJens Axboe 
188320ae51fSJens Axboe 		page += sprintf(page, "%8lu\t%lu\n", d, hctx->dispatched[i]);
189320ae51fSJens Axboe 	}
190320ae51fSJens Axboe 
191320ae51fSJens Axboe 	return page - start_page;
192320ae51fSJens Axboe }
193320ae51fSJens Axboe 
194320ae51fSJens Axboe static ssize_t blk_mq_hw_sysfs_rq_list_show(struct blk_mq_hw_ctx *hctx,
195320ae51fSJens Axboe 					    char *page)
196320ae51fSJens Axboe {
197320ae51fSJens Axboe 	ssize_t ret;
198320ae51fSJens Axboe 
199320ae51fSJens Axboe 	spin_lock(&hctx->lock);
200320ae51fSJens Axboe 	ret = sysfs_list_show(page, &hctx->dispatch, "HCTX pending");
201320ae51fSJens Axboe 	spin_unlock(&hctx->lock);
202320ae51fSJens Axboe 
203320ae51fSJens Axboe 	return ret;
204320ae51fSJens Axboe }
205320ae51fSJens Axboe 
206320ae51fSJens Axboe static ssize_t blk_mq_hw_sysfs_ipi_show(struct blk_mq_hw_ctx *hctx, char *page)
207320ae51fSJens Axboe {
208320ae51fSJens Axboe 	ssize_t ret;
209320ae51fSJens Axboe 
210320ae51fSJens Axboe 	spin_lock(&hctx->lock);
211320ae51fSJens Axboe 	ret = sprintf(page, "%u\n", !!(hctx->flags & BLK_MQ_F_SHOULD_IPI));
212320ae51fSJens Axboe 	spin_unlock(&hctx->lock);
213320ae51fSJens Axboe 
214320ae51fSJens Axboe 	return ret;
215320ae51fSJens Axboe }
216320ae51fSJens Axboe 
217320ae51fSJens Axboe static ssize_t blk_mq_hw_sysfs_ipi_store(struct blk_mq_hw_ctx *hctx,
218320ae51fSJens Axboe 					 const char *page, size_t len)
219320ae51fSJens Axboe {
220320ae51fSJens Axboe 	struct blk_mq_ctx *ctx;
221320ae51fSJens Axboe 	unsigned long ret;
222320ae51fSJens Axboe 	unsigned int i;
223320ae51fSJens Axboe 
224320ae51fSJens Axboe 	if (kstrtoul(page, 10, &ret)) {
225320ae51fSJens Axboe 		pr_err("blk-mq-sysfs: invalid input '%s'\n", page);
226320ae51fSJens Axboe 		return -EINVAL;
227320ae51fSJens Axboe 	}
228320ae51fSJens Axboe 
229320ae51fSJens Axboe 	spin_lock(&hctx->lock);
230320ae51fSJens Axboe 	if (ret)
231320ae51fSJens Axboe 		hctx->flags |= BLK_MQ_F_SHOULD_IPI;
232320ae51fSJens Axboe 	else
233320ae51fSJens Axboe 		hctx->flags &= ~BLK_MQ_F_SHOULD_IPI;
234320ae51fSJens Axboe 	spin_unlock(&hctx->lock);
235320ae51fSJens Axboe 
236320ae51fSJens Axboe 	hctx_for_each_ctx(hctx, ctx, i)
237320ae51fSJens Axboe 		ctx->ipi_redirect = !!ret;
238320ae51fSJens Axboe 
239320ae51fSJens Axboe 	return len;
240320ae51fSJens Axboe }
241320ae51fSJens Axboe 
242320ae51fSJens Axboe static ssize_t blk_mq_hw_sysfs_tags_show(struct blk_mq_hw_ctx *hctx, char *page)
243320ae51fSJens Axboe {
244320ae51fSJens Axboe 	return blk_mq_tag_sysfs_show(hctx->tags, page);
245320ae51fSJens Axboe }
246320ae51fSJens Axboe 
247320ae51fSJens Axboe static struct blk_mq_ctx_sysfs_entry blk_mq_sysfs_dispatched = {
248320ae51fSJens Axboe 	.attr = {.name = "dispatched", .mode = S_IRUGO },
249320ae51fSJens Axboe 	.show = blk_mq_sysfs_dispatched_show,
250320ae51fSJens Axboe };
251320ae51fSJens Axboe static struct blk_mq_ctx_sysfs_entry blk_mq_sysfs_merged = {
252320ae51fSJens Axboe 	.attr = {.name = "merged", .mode = S_IRUGO },
253320ae51fSJens Axboe 	.show = blk_mq_sysfs_merged_show,
254320ae51fSJens Axboe };
255320ae51fSJens Axboe static struct blk_mq_ctx_sysfs_entry blk_mq_sysfs_completed = {
256320ae51fSJens Axboe 	.attr = {.name = "completed", .mode = S_IRUGO },
257320ae51fSJens Axboe 	.show = blk_mq_sysfs_completed_show,
258320ae51fSJens Axboe };
259320ae51fSJens Axboe static struct blk_mq_ctx_sysfs_entry blk_mq_sysfs_rq_list = {
260320ae51fSJens Axboe 	.attr = {.name = "rq_list", .mode = S_IRUGO },
261320ae51fSJens Axboe 	.show = blk_mq_sysfs_rq_list_show,
262320ae51fSJens Axboe };
263320ae51fSJens Axboe 
264320ae51fSJens Axboe static struct attribute *default_ctx_attrs[] = {
265320ae51fSJens Axboe 	&blk_mq_sysfs_dispatched.attr,
266320ae51fSJens Axboe 	&blk_mq_sysfs_merged.attr,
267320ae51fSJens Axboe 	&blk_mq_sysfs_completed.attr,
268320ae51fSJens Axboe 	&blk_mq_sysfs_rq_list.attr,
269320ae51fSJens Axboe 	NULL,
270320ae51fSJens Axboe };
271320ae51fSJens Axboe 
272320ae51fSJens Axboe static struct blk_mq_hw_ctx_sysfs_entry blk_mq_hw_sysfs_queued = {
273320ae51fSJens Axboe 	.attr = {.name = "queued", .mode = S_IRUGO },
274320ae51fSJens Axboe 	.show = blk_mq_hw_sysfs_queued_show,
275320ae51fSJens Axboe };
276320ae51fSJens Axboe static struct blk_mq_hw_ctx_sysfs_entry blk_mq_hw_sysfs_run = {
277320ae51fSJens Axboe 	.attr = {.name = "run", .mode = S_IRUGO },
278320ae51fSJens Axboe 	.show = blk_mq_hw_sysfs_run_show,
279320ae51fSJens Axboe };
280320ae51fSJens Axboe static struct blk_mq_hw_ctx_sysfs_entry blk_mq_hw_sysfs_dispatched = {
281320ae51fSJens Axboe 	.attr = {.name = "dispatched", .mode = S_IRUGO },
282320ae51fSJens Axboe 	.show = blk_mq_hw_sysfs_dispatched_show,
283320ae51fSJens Axboe };
284320ae51fSJens Axboe static struct blk_mq_hw_ctx_sysfs_entry blk_mq_hw_sysfs_pending = {
285320ae51fSJens Axboe 	.attr = {.name = "pending", .mode = S_IRUGO },
286320ae51fSJens Axboe 	.show = blk_mq_hw_sysfs_rq_list_show,
287320ae51fSJens Axboe };
288320ae51fSJens Axboe static struct blk_mq_hw_ctx_sysfs_entry blk_mq_hw_sysfs_ipi = {
289320ae51fSJens Axboe 	.attr = {.name = "ipi_redirect", .mode = S_IRUGO | S_IWUSR},
290320ae51fSJens Axboe 	.show = blk_mq_hw_sysfs_ipi_show,
291320ae51fSJens Axboe 	.store = blk_mq_hw_sysfs_ipi_store,
292320ae51fSJens Axboe };
293320ae51fSJens Axboe static struct blk_mq_hw_ctx_sysfs_entry blk_mq_hw_sysfs_tags = {
294320ae51fSJens Axboe 	.attr = {.name = "tags", .mode = S_IRUGO },
295320ae51fSJens Axboe 	.show = blk_mq_hw_sysfs_tags_show,
296320ae51fSJens Axboe };
297320ae51fSJens Axboe 
298320ae51fSJens Axboe static struct attribute *default_hw_ctx_attrs[] = {
299320ae51fSJens Axboe 	&blk_mq_hw_sysfs_queued.attr,
300320ae51fSJens Axboe 	&blk_mq_hw_sysfs_run.attr,
301320ae51fSJens Axboe 	&blk_mq_hw_sysfs_dispatched.attr,
302320ae51fSJens Axboe 	&blk_mq_hw_sysfs_pending.attr,
303320ae51fSJens Axboe 	&blk_mq_hw_sysfs_ipi.attr,
304320ae51fSJens Axboe 	&blk_mq_hw_sysfs_tags.attr,
305320ae51fSJens Axboe 	NULL,
306320ae51fSJens Axboe };
307320ae51fSJens Axboe 
308320ae51fSJens Axboe static const struct sysfs_ops blk_mq_sysfs_ops = {
309320ae51fSJens Axboe 	.show	= blk_mq_sysfs_show,
310320ae51fSJens Axboe 	.store	= blk_mq_sysfs_store,
311320ae51fSJens Axboe };
312320ae51fSJens Axboe 
313320ae51fSJens Axboe static const struct sysfs_ops blk_mq_hw_sysfs_ops = {
314320ae51fSJens Axboe 	.show	= blk_mq_hw_sysfs_show,
315320ae51fSJens Axboe 	.store	= blk_mq_hw_sysfs_store,
316320ae51fSJens Axboe };
317320ae51fSJens Axboe 
318320ae51fSJens Axboe static struct kobj_type blk_mq_ktype = {
319320ae51fSJens Axboe 	.sysfs_ops	= &blk_mq_sysfs_ops,
320320ae51fSJens Axboe 	.release	= blk_mq_sysfs_release,
321320ae51fSJens Axboe };
322320ae51fSJens Axboe 
323320ae51fSJens Axboe static struct kobj_type blk_mq_ctx_ktype = {
324320ae51fSJens Axboe 	.sysfs_ops	= &blk_mq_sysfs_ops,
325320ae51fSJens Axboe 	.default_attrs	= default_ctx_attrs,
326320ae51fSJens Axboe 	.release	= blk_mq_sysfs_release,
327320ae51fSJens Axboe };
328320ae51fSJens Axboe 
329320ae51fSJens Axboe static struct kobj_type blk_mq_hw_ktype = {
330320ae51fSJens Axboe 	.sysfs_ops	= &blk_mq_hw_sysfs_ops,
331320ae51fSJens Axboe 	.default_attrs	= default_hw_ctx_attrs,
332320ae51fSJens Axboe 	.release	= blk_mq_sysfs_release,
333320ae51fSJens Axboe };
334320ae51fSJens Axboe 
335320ae51fSJens Axboe void blk_mq_unregister_disk(struct gendisk *disk)
336320ae51fSJens Axboe {
337320ae51fSJens Axboe 	struct request_queue *q = disk->queue;
338*85157366SAndrey Vagin 	struct blk_mq_hw_ctx *hctx;
339*85157366SAndrey Vagin 	struct blk_mq_ctx *ctx;
340*85157366SAndrey Vagin 	int i, j;
341*85157366SAndrey Vagin 
342*85157366SAndrey Vagin 	queue_for_each_hw_ctx(q, hctx, i) {
343*85157366SAndrey Vagin 		hctx_for_each_ctx(hctx, ctx, j) {
344*85157366SAndrey Vagin 			kobject_del(&ctx->kobj);
345*85157366SAndrey Vagin 			kobject_put(&ctx->kobj);
346*85157366SAndrey Vagin 		}
347*85157366SAndrey Vagin 		kobject_del(&hctx->kobj);
348*85157366SAndrey Vagin 		kobject_put(&hctx->kobj);
349*85157366SAndrey Vagin 	}
350320ae51fSJens Axboe 
351320ae51fSJens Axboe 	kobject_uevent(&q->mq_kobj, KOBJ_REMOVE);
352320ae51fSJens Axboe 	kobject_del(&q->mq_kobj);
353*85157366SAndrey Vagin 	kobject_put(&q->mq_kobj);
354320ae51fSJens Axboe 
355320ae51fSJens Axboe 	kobject_put(&disk_to_dev(disk)->kobj);
356320ae51fSJens Axboe }
357320ae51fSJens Axboe 
358320ae51fSJens Axboe int blk_mq_register_disk(struct gendisk *disk)
359320ae51fSJens Axboe {
360320ae51fSJens Axboe 	struct device *dev = disk_to_dev(disk);
361320ae51fSJens Axboe 	struct request_queue *q = disk->queue;
362320ae51fSJens Axboe 	struct blk_mq_hw_ctx *hctx;
363320ae51fSJens Axboe 	struct blk_mq_ctx *ctx;
364320ae51fSJens Axboe 	int ret, i, j;
365320ae51fSJens Axboe 
366320ae51fSJens Axboe 	kobject_init(&q->mq_kobj, &blk_mq_ktype);
367320ae51fSJens Axboe 
368320ae51fSJens Axboe 	ret = kobject_add(&q->mq_kobj, kobject_get(&dev->kobj), "%s", "mq");
369320ae51fSJens Axboe 	if (ret < 0)
370320ae51fSJens Axboe 		return ret;
371320ae51fSJens Axboe 
372320ae51fSJens Axboe 	kobject_uevent(&q->mq_kobj, KOBJ_ADD);
373320ae51fSJens Axboe 
374320ae51fSJens Axboe 	queue_for_each_hw_ctx(q, hctx, i) {
375320ae51fSJens Axboe 		kobject_init(&hctx->kobj, &blk_mq_hw_ktype);
376320ae51fSJens Axboe 		ret = kobject_add(&hctx->kobj, &q->mq_kobj, "%u", i);
377320ae51fSJens Axboe 		if (ret)
378320ae51fSJens Axboe 			break;
379320ae51fSJens Axboe 
380320ae51fSJens Axboe 		if (!hctx->nr_ctx)
381320ae51fSJens Axboe 			continue;
382320ae51fSJens Axboe 
383320ae51fSJens Axboe 		hctx_for_each_ctx(hctx, ctx, j) {
384320ae51fSJens Axboe 			kobject_init(&ctx->kobj, &blk_mq_ctx_ktype);
385320ae51fSJens Axboe 			ret = kobject_add(&ctx->kobj, &hctx->kobj, "cpu%u", ctx->cpu);
386320ae51fSJens Axboe 			if (ret)
387320ae51fSJens Axboe 				break;
388320ae51fSJens Axboe 		}
389320ae51fSJens Axboe 	}
390320ae51fSJens Axboe 
391320ae51fSJens Axboe 	if (ret) {
392320ae51fSJens Axboe 		blk_mq_unregister_disk(disk);
393320ae51fSJens Axboe 		return ret;
394320ae51fSJens Axboe 	}
395320ae51fSJens Axboe 
396320ae51fSJens Axboe 	return 0;
397320ae51fSJens Axboe }
398