xref: /linux/drivers/gpu/drm/vkms/vkms_configfs.c (revision face6a3615a649456eb4549f6d474221d877d604)
1 // SPDX-License-Identifier: GPL-2.0+
2 #include <linux/cleanup.h>
3 #include <linux/configfs.h>
4 #include <linux/mutex.h>
5 #include <linux/slab.h>
6 
7 #include "vkms_drv.h"
8 #include "vkms_config.h"
9 #include "vkms_configfs.h"
10 #include "vkms_connector.h"
11 
12 /* To avoid registering configfs more than once or unregistering on error */
13 static bool is_configfs_registered;
14 
15 /**
16  * struct vkms_configfs_device - Configfs representation of a VKMS device
17  *
18  * @group: Top level configuration group that represents a VKMS device.
19  * Initialized when a new directory is created under "/config/vkms/"
20  * @planes_group: Default subgroup of @group at "/config/vkms/planes"
21  * @crtcs_group: Default subgroup of @group at "/config/vkms/crtcs"
22  * @encoders_group: Default subgroup of @group at "/config/vkms/encoders"
23  * @connectors_group: Default subgroup of @group at "/config/vkms/connectors"
24  * @lock: Lock used to project concurrent access to the configuration attributes
25  * @config: Protected by @lock. Configuration of the VKMS device
26  * @enabled: Protected by @lock. The device is created or destroyed when this
27  * option changes
28  */
29 struct vkms_configfs_device {
30 	struct config_group group;
31 	struct config_group planes_group;
32 	struct config_group crtcs_group;
33 	struct config_group encoders_group;
34 	struct config_group connectors_group;
35 
36 	struct mutex lock;
37 	struct vkms_config *config;
38 	bool enabled;
39 };
40 
41 /**
42  * struct vkms_configfs_plane - Configfs representation of a plane
43  *
44  * @group: Top level configuration group that represents a plane.
45  * Initialized when a new directory is created under "/config/vkms/planes"
46  * @possible_crtcs_group: Default subgroup of @group at "plane/possible_crtcs"
47  * @dev: The vkms_configfs_device this plane belongs to
48  * @config: Configuration of the VKMS plane
49  */
50 struct vkms_configfs_plane {
51 	struct config_group group;
52 	struct config_group possible_crtcs_group;
53 	struct vkms_configfs_device *dev;
54 	struct vkms_config_plane *config;
55 };
56 
57 /**
58  * struct vkms_configfs_crtc - Configfs representation of a CRTC
59  *
60  * @group: Top level configuration group that represents a CRTC.
61  * Initialized when a new directory is created under "/config/vkms/crtcs"
62  * @dev: The vkms_configfs_device this CRTC belongs to
63  * @config: Configuration of the VKMS CRTC
64  */
65 struct vkms_configfs_crtc {
66 	struct config_group group;
67 	struct vkms_configfs_device *dev;
68 	struct vkms_config_crtc *config;
69 };
70 
71 /**
72  * struct vkms_configfs_encoder - Configfs representation of a encoder
73  *
74  * @group: Top level configuration group that represents a encoder.
75  * Initialized when a new directory is created under "/config/vkms/encoders"
76  * @possible_crtcs_group: Default subgroup of @group at "encoder/possible_crtcs"
77  * @dev: The vkms_configfs_device this encoder belongs to
78  * @config: Configuration of the VKMS encoder
79  */
80 struct vkms_configfs_encoder {
81 	struct config_group group;
82 	struct config_group possible_crtcs_group;
83 	struct vkms_configfs_device *dev;
84 	struct vkms_config_encoder *config;
85 };
86 
87 /**
88  * struct vkms_configfs_connector - Configfs representation of a connector
89  *
90  * @group: Top level configuration group that represents a connector.
91  * Initialized when a new directory is created under "/config/vkms/connectors"
92  * @possible_encoders_group: Default subgroup of @group at
93  * "connector/possible_encoders"
94  * @dev: The vkms_configfs_device this connector belongs to
95  * @config: Configuration of the VKMS connector
96  */
97 struct vkms_configfs_connector {
98 	struct config_group group;
99 	struct config_group possible_encoders_group;
100 	struct vkms_configfs_device *dev;
101 	struct vkms_config_connector *config;
102 };
103 
104 #define device_item_to_vkms_configfs_device(item) \
105 	container_of(to_config_group((item)), struct vkms_configfs_device, \
106 		     group)
107 
108 #define child_group_to_vkms_configfs_device(group) \
109 	device_item_to_vkms_configfs_device((&(group)->cg_item)->ci_parent)
110 
111 #define plane_item_to_vkms_configfs_plane(item) \
112 	container_of(to_config_group((item)), struct vkms_configfs_plane, group)
113 
114 #define plane_possible_crtcs_item_to_vkms_configfs_plane(item) \
115 	container_of(to_config_group((item)), struct vkms_configfs_plane, \
116 		     possible_crtcs_group)
117 
118 #define crtc_item_to_vkms_configfs_crtc(item) \
119 	container_of(to_config_group((item)), struct vkms_configfs_crtc, group)
120 
121 #define encoder_item_to_vkms_configfs_encoder(item) \
122 	container_of(to_config_group((item)), struct vkms_configfs_encoder, \
123 		     group)
124 
125 #define encoder_possible_crtcs_item_to_vkms_configfs_encoder(item) \
126 	container_of(to_config_group((item)), struct vkms_configfs_encoder, \
127 		     possible_crtcs_group)
128 
129 #define connector_item_to_vkms_configfs_connector(item) \
130 	container_of(to_config_group((item)), struct vkms_configfs_connector, \
131 		     group)
132 
133 #define connector_possible_encoders_item_to_vkms_configfs_connector(item) \
134 	container_of(to_config_group((item)), struct vkms_configfs_connector, \
135 		     possible_encoders_group)
136 
137 static ssize_t crtc_writeback_show(struct config_item *item, char *page)
138 {
139 	struct vkms_configfs_crtc *crtc;
140 	bool writeback;
141 
142 	crtc = crtc_item_to_vkms_configfs_crtc(item);
143 
144 	scoped_guard(mutex, &crtc->dev->lock)
145 		writeback = vkms_config_crtc_get_writeback(crtc->config);
146 
147 	return sprintf(page, "%d\n", writeback);
148 }
149 
150 static ssize_t crtc_writeback_store(struct config_item *item, const char *page,
151 				    size_t count)
152 {
153 	struct vkms_configfs_crtc *crtc;
154 	bool writeback;
155 
156 	crtc = crtc_item_to_vkms_configfs_crtc(item);
157 
158 	if (kstrtobool(page, &writeback))
159 		return -EINVAL;
160 
161 	scoped_guard(mutex, &crtc->dev->lock) {
162 		if (crtc->dev->enabled)
163 			return -EBUSY;
164 
165 		vkms_config_crtc_set_writeback(crtc->config, writeback);
166 	}
167 
168 	return (ssize_t)count;
169 }
170 
171 CONFIGFS_ATTR(crtc_, writeback);
172 
173 static struct configfs_attribute *crtc_item_attrs[] = {
174 	&crtc_attr_writeback,
175 	NULL,
176 };
177 
178 static void crtc_release(struct config_item *item)
179 {
180 	struct vkms_configfs_crtc *crtc;
181 	struct mutex *lock;
182 
183 	crtc = crtc_item_to_vkms_configfs_crtc(item);
184 	lock = &crtc->dev->lock;
185 
186 	scoped_guard(mutex, lock) {
187 		vkms_config_destroy_crtc(crtc->dev->config, crtc->config);
188 		kfree(crtc);
189 	}
190 }
191 
192 static struct configfs_item_operations crtc_item_operations = {
193 	.release	= &crtc_release,
194 };
195 
196 static const struct config_item_type crtc_item_type = {
197 	.ct_attrs	= crtc_item_attrs,
198 	.ct_item_ops	= &crtc_item_operations,
199 	.ct_owner	= THIS_MODULE,
200 };
201 
202 static struct config_group *make_crtc_group(struct config_group *group,
203 					    const char *name)
204 {
205 	struct vkms_configfs_device *dev;
206 	struct vkms_configfs_crtc *crtc;
207 
208 	dev = child_group_to_vkms_configfs_device(group);
209 
210 	scoped_guard(mutex, &dev->lock) {
211 		if (dev->enabled)
212 			return ERR_PTR(-EBUSY);
213 
214 		crtc = kzalloc(sizeof(*crtc), GFP_KERNEL);
215 		if (!crtc)
216 			return ERR_PTR(-ENOMEM);
217 
218 		crtc->dev = dev;
219 
220 		crtc->config = vkms_config_create_crtc(dev->config);
221 		if (IS_ERR(crtc->config)) {
222 			kfree(crtc);
223 			return ERR_CAST(crtc->config);
224 		}
225 
226 		config_group_init_type_name(&crtc->group, name, &crtc_item_type);
227 	}
228 
229 	return &crtc->group;
230 }
231 
232 static struct configfs_group_operations crtcs_group_operations = {
233 	.make_group	= &make_crtc_group,
234 };
235 
236 static const struct config_item_type crtc_group_type = {
237 	.ct_group_ops	= &crtcs_group_operations,
238 	.ct_owner	= THIS_MODULE,
239 };
240 
241 static int plane_possible_crtcs_allow_link(struct config_item *src,
242 					   struct config_item *target)
243 {
244 	struct vkms_configfs_plane *plane;
245 	struct vkms_configfs_crtc *crtc;
246 	int ret;
247 
248 	if (target->ci_type != &crtc_item_type)
249 		return -EINVAL;
250 
251 	plane = plane_possible_crtcs_item_to_vkms_configfs_plane(src);
252 	crtc = crtc_item_to_vkms_configfs_crtc(target);
253 
254 	scoped_guard(mutex, &plane->dev->lock) {
255 		if (plane->dev->enabled)
256 			return -EBUSY;
257 
258 		ret = vkms_config_plane_attach_crtc(plane->config, crtc->config);
259 	}
260 
261 	return ret;
262 }
263 
264 static void plane_possible_crtcs_drop_link(struct config_item *src,
265 					   struct config_item *target)
266 {
267 	struct vkms_configfs_plane *plane;
268 	struct vkms_configfs_crtc *crtc;
269 
270 	plane = plane_possible_crtcs_item_to_vkms_configfs_plane(src);
271 	crtc = crtc_item_to_vkms_configfs_crtc(target);
272 
273 	scoped_guard(mutex, &plane->dev->lock)
274 		vkms_config_plane_detach_crtc(plane->config, crtc->config);
275 }
276 
277 static struct configfs_item_operations plane_possible_crtcs_item_operations = {
278 	.allow_link	= plane_possible_crtcs_allow_link,
279 	.drop_link	= plane_possible_crtcs_drop_link,
280 };
281 
282 static const struct config_item_type plane_possible_crtcs_group_type = {
283 	.ct_item_ops	= &plane_possible_crtcs_item_operations,
284 	.ct_owner	= THIS_MODULE,
285 };
286 
287 static ssize_t plane_type_show(struct config_item *item, char *page)
288 {
289 	struct vkms_configfs_plane *plane;
290 	enum drm_plane_type type;
291 
292 	plane = plane_item_to_vkms_configfs_plane(item);
293 
294 	scoped_guard(mutex, &plane->dev->lock)
295 		type = vkms_config_plane_get_type(plane->config);
296 
297 	return sprintf(page, "%u", type);
298 }
299 
300 static ssize_t plane_type_store(struct config_item *item, const char *page,
301 				size_t count)
302 {
303 	struct vkms_configfs_plane *plane;
304 	enum drm_plane_type type;
305 
306 	plane = plane_item_to_vkms_configfs_plane(item);
307 
308 	if (kstrtouint(page, 10, &type))
309 		return -EINVAL;
310 
311 	if (type != DRM_PLANE_TYPE_OVERLAY && type != DRM_PLANE_TYPE_PRIMARY &&
312 	    type != DRM_PLANE_TYPE_CURSOR)
313 		return -EINVAL;
314 
315 	scoped_guard(mutex, &plane->dev->lock) {
316 		if (plane->dev->enabled)
317 			return -EBUSY;
318 
319 		vkms_config_plane_set_type(plane->config, type);
320 	}
321 
322 	return (ssize_t)count;
323 }
324 
325 CONFIGFS_ATTR(plane_, type);
326 
327 static struct configfs_attribute *plane_item_attrs[] = {
328 	&plane_attr_type,
329 	NULL,
330 };
331 
332 static void plane_release(struct config_item *item)
333 {
334 	struct vkms_configfs_plane *plane;
335 	struct mutex *lock;
336 
337 	plane = plane_item_to_vkms_configfs_plane(item);
338 	lock = &plane->dev->lock;
339 
340 	scoped_guard(mutex, lock) {
341 		vkms_config_destroy_plane(plane->config);
342 		kfree(plane);
343 	}
344 }
345 
346 static struct configfs_item_operations plane_item_operations = {
347 	.release	= &plane_release,
348 };
349 
350 static const struct config_item_type plane_item_type = {
351 	.ct_attrs	= plane_item_attrs,
352 	.ct_item_ops	= &plane_item_operations,
353 	.ct_owner	= THIS_MODULE,
354 };
355 
356 static struct config_group *make_plane_group(struct config_group *group,
357 					     const char *name)
358 {
359 	struct vkms_configfs_device *dev;
360 	struct vkms_configfs_plane *plane;
361 
362 	dev = child_group_to_vkms_configfs_device(group);
363 
364 	scoped_guard(mutex, &dev->lock) {
365 		if (dev->enabled)
366 			return ERR_PTR(-EBUSY);
367 
368 		plane = kzalloc(sizeof(*plane), GFP_KERNEL);
369 		if (!plane)
370 			return ERR_PTR(-ENOMEM);
371 
372 		plane->dev = dev;
373 
374 		plane->config = vkms_config_create_plane(dev->config);
375 		if (IS_ERR(plane->config)) {
376 			kfree(plane);
377 			return ERR_CAST(plane->config);
378 		}
379 
380 		config_group_init_type_name(&plane->group, name, &plane_item_type);
381 
382 		config_group_init_type_name(&plane->possible_crtcs_group,
383 					    "possible_crtcs",
384 					    &plane_possible_crtcs_group_type);
385 		configfs_add_default_group(&plane->possible_crtcs_group,
386 					   &plane->group);
387 	}
388 
389 	return &plane->group;
390 }
391 
392 static struct configfs_group_operations planes_group_operations = {
393 	.make_group	= &make_plane_group,
394 };
395 
396 static const struct config_item_type plane_group_type = {
397 	.ct_group_ops	= &planes_group_operations,
398 	.ct_owner	= THIS_MODULE,
399 };
400 
401 static int encoder_possible_crtcs_allow_link(struct config_item *src,
402 					     struct config_item *target)
403 {
404 	struct vkms_configfs_encoder *encoder;
405 	struct vkms_configfs_crtc *crtc;
406 	int ret;
407 
408 	if (target->ci_type != &crtc_item_type)
409 		return -EINVAL;
410 
411 	encoder = encoder_possible_crtcs_item_to_vkms_configfs_encoder(src);
412 	crtc = crtc_item_to_vkms_configfs_crtc(target);
413 
414 	scoped_guard(mutex, &encoder->dev->lock) {
415 		if (encoder->dev->enabled)
416 			return -EBUSY;
417 
418 		ret = vkms_config_encoder_attach_crtc(encoder->config, crtc->config);
419 	}
420 
421 	return ret;
422 }
423 
424 static void encoder_possible_crtcs_drop_link(struct config_item *src,
425 					     struct config_item *target)
426 {
427 	struct vkms_configfs_encoder *encoder;
428 	struct vkms_configfs_crtc *crtc;
429 
430 	encoder = encoder_possible_crtcs_item_to_vkms_configfs_encoder(src);
431 	crtc = crtc_item_to_vkms_configfs_crtc(target);
432 
433 	scoped_guard(mutex, &encoder->dev->lock)
434 		vkms_config_encoder_detach_crtc(encoder->config, crtc->config);
435 }
436 
437 static struct configfs_item_operations encoder_possible_crtcs_item_operations = {
438 	.allow_link	= encoder_possible_crtcs_allow_link,
439 	.drop_link	= encoder_possible_crtcs_drop_link,
440 };
441 
442 static const struct config_item_type encoder_possible_crtcs_group_type = {
443 	.ct_item_ops	= &encoder_possible_crtcs_item_operations,
444 	.ct_owner	= THIS_MODULE,
445 };
446 
447 static void encoder_release(struct config_item *item)
448 {
449 	struct vkms_configfs_encoder *encoder;
450 	struct mutex *lock;
451 
452 	encoder = encoder_item_to_vkms_configfs_encoder(item);
453 	lock = &encoder->dev->lock;
454 
455 	scoped_guard(mutex, lock) {
456 		vkms_config_destroy_encoder(encoder->dev->config, encoder->config);
457 		kfree(encoder);
458 	}
459 }
460 
461 static struct configfs_item_operations encoder_item_operations = {
462 	.release	= &encoder_release,
463 };
464 
465 static const struct config_item_type encoder_item_type = {
466 	.ct_item_ops	= &encoder_item_operations,
467 	.ct_owner	= THIS_MODULE,
468 };
469 
470 static struct config_group *make_encoder_group(struct config_group *group,
471 					       const char *name)
472 {
473 	struct vkms_configfs_device *dev;
474 	struct vkms_configfs_encoder *encoder;
475 
476 	dev = child_group_to_vkms_configfs_device(group);
477 
478 	scoped_guard(mutex, &dev->lock) {
479 		if (dev->enabled)
480 			return ERR_PTR(-EBUSY);
481 
482 		encoder = kzalloc(sizeof(*encoder), GFP_KERNEL);
483 		if (!encoder)
484 			return ERR_PTR(-ENOMEM);
485 
486 		encoder->dev = dev;
487 
488 		encoder->config = vkms_config_create_encoder(dev->config);
489 		if (IS_ERR(encoder->config)) {
490 			kfree(encoder);
491 			return ERR_CAST(encoder->config);
492 		}
493 
494 		config_group_init_type_name(&encoder->group, name,
495 					    &encoder_item_type);
496 
497 		config_group_init_type_name(&encoder->possible_crtcs_group,
498 					    "possible_crtcs",
499 					    &encoder_possible_crtcs_group_type);
500 		configfs_add_default_group(&encoder->possible_crtcs_group,
501 					   &encoder->group);
502 	}
503 
504 	return &encoder->group;
505 }
506 
507 static struct configfs_group_operations encoders_group_operations = {
508 	.make_group	= &make_encoder_group,
509 };
510 
511 static const struct config_item_type encoder_group_type = {
512 	.ct_group_ops	= &encoders_group_operations,
513 	.ct_owner	= THIS_MODULE,
514 };
515 
516 static ssize_t connector_status_show(struct config_item *item, char *page)
517 {
518 	struct vkms_configfs_connector *connector;
519 	enum drm_connector_status status;
520 
521 	connector = connector_item_to_vkms_configfs_connector(item);
522 
523 	scoped_guard(mutex, &connector->dev->lock)
524 		status = vkms_config_connector_get_status(connector->config);
525 
526 	return sprintf(page, "%u", status);
527 }
528 
529 static ssize_t connector_status_store(struct config_item *item,
530 				      const char *page, size_t count)
531 {
532 	struct vkms_configfs_connector *connector;
533 	enum drm_connector_status status;
534 
535 	connector = connector_item_to_vkms_configfs_connector(item);
536 
537 	if (kstrtouint(page, 10, &status))
538 		return -EINVAL;
539 
540 	if (status != connector_status_connected &&
541 	    status != connector_status_disconnected &&
542 	    status != connector_status_unknown)
543 		return -EINVAL;
544 
545 	scoped_guard(mutex, &connector->dev->lock) {
546 		vkms_config_connector_set_status(connector->config, status);
547 
548 		if (connector->dev->enabled)
549 			vkms_trigger_connector_hotplug(connector->dev->config->dev);
550 	}
551 
552 	return (ssize_t)count;
553 }
554 
555 CONFIGFS_ATTR(connector_, status);
556 
557 static struct configfs_attribute *connector_item_attrs[] = {
558 	&connector_attr_status,
559 	NULL,
560 };
561 
562 static void connector_release(struct config_item *item)
563 {
564 	struct vkms_configfs_connector *connector;
565 	struct mutex *lock;
566 
567 	connector = connector_item_to_vkms_configfs_connector(item);
568 	lock = &connector->dev->lock;
569 
570 	scoped_guard(mutex, lock) {
571 		vkms_config_destroy_connector(connector->config);
572 		kfree(connector);
573 	}
574 }
575 
576 static struct configfs_item_operations connector_item_operations = {
577 	.release	= &connector_release,
578 };
579 
580 static const struct config_item_type connector_item_type = {
581 	.ct_attrs	= connector_item_attrs,
582 	.ct_item_ops	= &connector_item_operations,
583 	.ct_owner	= THIS_MODULE,
584 };
585 
586 static int connector_possible_encoders_allow_link(struct config_item *src,
587 						  struct config_item *target)
588 {
589 	struct vkms_configfs_connector *connector;
590 	struct vkms_configfs_encoder *encoder;
591 	int ret;
592 
593 	if (target->ci_type != &encoder_item_type)
594 		return -EINVAL;
595 
596 	connector = connector_possible_encoders_item_to_vkms_configfs_connector(src);
597 	encoder = encoder_item_to_vkms_configfs_encoder(target);
598 
599 	scoped_guard(mutex, &connector->dev->lock) {
600 		if (connector->dev->enabled)
601 			return -EBUSY;
602 
603 		ret = vkms_config_connector_attach_encoder(connector->config,
604 							   encoder->config);
605 	}
606 
607 	return ret;
608 }
609 
610 static void connector_possible_encoders_drop_link(struct config_item *src,
611 						  struct config_item *target)
612 {
613 	struct vkms_configfs_connector *connector;
614 	struct vkms_configfs_encoder *encoder;
615 
616 	connector = connector_possible_encoders_item_to_vkms_configfs_connector(src);
617 	encoder = encoder_item_to_vkms_configfs_encoder(target);
618 
619 	scoped_guard(mutex, &connector->dev->lock) {
620 		vkms_config_connector_detach_encoder(connector->config,
621 						     encoder->config);
622 	}
623 }
624 
625 static struct configfs_item_operations connector_possible_encoders_item_operations = {
626 	.allow_link	= connector_possible_encoders_allow_link,
627 	.drop_link	= connector_possible_encoders_drop_link,
628 };
629 
630 static const struct config_item_type connector_possible_encoders_group_type = {
631 	.ct_item_ops	= &connector_possible_encoders_item_operations,
632 	.ct_owner	= THIS_MODULE,
633 };
634 
635 static struct config_group *make_connector_group(struct config_group *group,
636 						 const char *name)
637 {
638 	struct vkms_configfs_device *dev;
639 	struct vkms_configfs_connector *connector;
640 
641 	dev = child_group_to_vkms_configfs_device(group);
642 
643 	scoped_guard(mutex, &dev->lock) {
644 		if (dev->enabled)
645 			return ERR_PTR(-EBUSY);
646 
647 		connector = kzalloc(sizeof(*connector), GFP_KERNEL);
648 		if (!connector)
649 			return ERR_PTR(-ENOMEM);
650 
651 		connector->dev = dev;
652 
653 		connector->config = vkms_config_create_connector(dev->config);
654 		if (IS_ERR(connector->config)) {
655 			kfree(connector);
656 			return ERR_CAST(connector->config);
657 		}
658 
659 		config_group_init_type_name(&connector->group, name,
660 					    &connector_item_type);
661 
662 		config_group_init_type_name(&connector->possible_encoders_group,
663 					    "possible_encoders",
664 					    &connector_possible_encoders_group_type);
665 		configfs_add_default_group(&connector->possible_encoders_group,
666 					   &connector->group);
667 	}
668 
669 	return &connector->group;
670 }
671 
672 static struct configfs_group_operations connectors_group_operations = {
673 	.make_group	= &make_connector_group,
674 };
675 
676 static const struct config_item_type connector_group_type = {
677 	.ct_group_ops	= &connectors_group_operations,
678 	.ct_owner	= THIS_MODULE,
679 };
680 
681 static ssize_t device_enabled_show(struct config_item *item, char *page)
682 {
683 	struct vkms_configfs_device *dev;
684 	bool enabled;
685 
686 	dev = device_item_to_vkms_configfs_device(item);
687 
688 	scoped_guard(mutex, &dev->lock)
689 		enabled = dev->enabled;
690 
691 	return sprintf(page, "%d\n", enabled);
692 }
693 
694 static ssize_t device_enabled_store(struct config_item *item, const char *page,
695 				    size_t count)
696 {
697 	struct vkms_configfs_device *dev;
698 	bool enabled;
699 	int ret = 0;
700 
701 	dev = device_item_to_vkms_configfs_device(item);
702 
703 	if (kstrtobool(page, &enabled))
704 		return -EINVAL;
705 
706 	scoped_guard(mutex, &dev->lock) {
707 		if (!dev->enabled && enabled) {
708 			if (!vkms_config_is_valid(dev->config))
709 				return -EINVAL;
710 
711 			ret = vkms_create(dev->config);
712 			if (ret)
713 				return ret;
714 		} else if (dev->enabled && !enabled) {
715 			vkms_destroy(dev->config);
716 		}
717 
718 		dev->enabled = enabled;
719 	}
720 
721 	return (ssize_t)count;
722 }
723 
724 CONFIGFS_ATTR(device_, enabled);
725 
726 static struct configfs_attribute *device_item_attrs[] = {
727 	&device_attr_enabled,
728 	NULL,
729 };
730 
731 static void device_release(struct config_item *item)
732 {
733 	struct vkms_configfs_device *dev;
734 
735 	dev = device_item_to_vkms_configfs_device(item);
736 
737 	if (dev->enabled)
738 		vkms_destroy(dev->config);
739 
740 	mutex_destroy(&dev->lock);
741 	vkms_config_destroy(dev->config);
742 	kfree(dev);
743 }
744 
745 static struct configfs_item_operations device_item_operations = {
746 	.release	= &device_release,
747 };
748 
749 static const struct config_item_type device_item_type = {
750 	.ct_attrs	= device_item_attrs,
751 	.ct_item_ops	= &device_item_operations,
752 	.ct_owner	= THIS_MODULE,
753 };
754 
755 static struct config_group *make_device_group(struct config_group *group,
756 					      const char *name)
757 {
758 	struct vkms_configfs_device *dev;
759 
760 	if (strcmp(name, DEFAULT_DEVICE_NAME) == 0)
761 		return ERR_PTR(-EINVAL);
762 
763 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
764 	if (!dev)
765 		return ERR_PTR(-ENOMEM);
766 
767 	dev->config = vkms_config_create(name);
768 	if (IS_ERR(dev->config)) {
769 		kfree(dev);
770 		return ERR_CAST(dev->config);
771 	}
772 
773 	config_group_init_type_name(&dev->group, name, &device_item_type);
774 	mutex_init(&dev->lock);
775 
776 	config_group_init_type_name(&dev->planes_group, "planes",
777 				    &plane_group_type);
778 	configfs_add_default_group(&dev->planes_group, &dev->group);
779 
780 	config_group_init_type_name(&dev->crtcs_group, "crtcs",
781 				    &crtc_group_type);
782 	configfs_add_default_group(&dev->crtcs_group, &dev->group);
783 
784 	config_group_init_type_name(&dev->encoders_group, "encoders",
785 				    &encoder_group_type);
786 	configfs_add_default_group(&dev->encoders_group, &dev->group);
787 
788 	config_group_init_type_name(&dev->connectors_group, "connectors",
789 				    &connector_group_type);
790 	configfs_add_default_group(&dev->connectors_group, &dev->group);
791 
792 	return &dev->group;
793 }
794 
795 static struct configfs_group_operations device_group_ops = {
796 	.make_group = &make_device_group,
797 };
798 
799 static const struct config_item_type device_group_type = {
800 	.ct_group_ops	= &device_group_ops,
801 	.ct_owner	= THIS_MODULE,
802 };
803 
804 static struct configfs_subsystem vkms_subsys = {
805 	.su_group = {
806 		.cg_item = {
807 			.ci_name = "vkms",
808 			.ci_type = &device_group_type,
809 		},
810 	},
811 	.su_mutex = __MUTEX_INITIALIZER(vkms_subsys.su_mutex),
812 };
813 
814 int vkms_configfs_register(void)
815 {
816 	int ret;
817 
818 	if (is_configfs_registered)
819 		return 0;
820 
821 	config_group_init(&vkms_subsys.su_group);
822 	ret = configfs_register_subsystem(&vkms_subsys);
823 
824 	is_configfs_registered = ret == 0;
825 
826 	return ret;
827 }
828 
829 void vkms_configfs_unregister(void)
830 {
831 	if (is_configfs_registered)
832 		configfs_unregister_subsystem(&vkms_subsys);
833 }
834