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 int ret; 208 209 dev = child_group_to_vkms_configfs_device(group); 210 211 scoped_guard(mutex, &dev->lock) { 212 if (dev->enabled) 213 return ERR_PTR(-EBUSY); 214 215 crtc = kzalloc(sizeof(*crtc), GFP_KERNEL); 216 if (!crtc) 217 return ERR_PTR(-ENOMEM); 218 219 crtc->dev = dev; 220 221 crtc->config = vkms_config_create_crtc(dev->config); 222 if (IS_ERR(crtc->config)) { 223 ret = PTR_ERR(crtc->config); 224 kfree(crtc); 225 return ERR_PTR(ret); 226 } 227 228 config_group_init_type_name(&crtc->group, name, &crtc_item_type); 229 } 230 231 return &crtc->group; 232 } 233 234 static struct configfs_group_operations crtcs_group_operations = { 235 .make_group = &make_crtc_group, 236 }; 237 238 static const struct config_item_type crtc_group_type = { 239 .ct_group_ops = &crtcs_group_operations, 240 .ct_owner = THIS_MODULE, 241 }; 242 243 static int plane_possible_crtcs_allow_link(struct config_item *src, 244 struct config_item *target) 245 { 246 struct vkms_configfs_plane *plane; 247 struct vkms_configfs_crtc *crtc; 248 int ret; 249 250 if (target->ci_type != &crtc_item_type) 251 return -EINVAL; 252 253 plane = plane_possible_crtcs_item_to_vkms_configfs_plane(src); 254 crtc = crtc_item_to_vkms_configfs_crtc(target); 255 256 scoped_guard(mutex, &plane->dev->lock) { 257 if (plane->dev->enabled) 258 return -EBUSY; 259 260 ret = vkms_config_plane_attach_crtc(plane->config, crtc->config); 261 } 262 263 return ret; 264 } 265 266 static void plane_possible_crtcs_drop_link(struct config_item *src, 267 struct config_item *target) 268 { 269 struct vkms_configfs_plane *plane; 270 struct vkms_configfs_crtc *crtc; 271 272 plane = plane_possible_crtcs_item_to_vkms_configfs_plane(src); 273 crtc = crtc_item_to_vkms_configfs_crtc(target); 274 275 scoped_guard(mutex, &plane->dev->lock) 276 vkms_config_plane_detach_crtc(plane->config, crtc->config); 277 } 278 279 static struct configfs_item_operations plane_possible_crtcs_item_operations = { 280 .allow_link = plane_possible_crtcs_allow_link, 281 .drop_link = plane_possible_crtcs_drop_link, 282 }; 283 284 static const struct config_item_type plane_possible_crtcs_group_type = { 285 .ct_item_ops = &plane_possible_crtcs_item_operations, 286 .ct_owner = THIS_MODULE, 287 }; 288 289 static ssize_t plane_type_show(struct config_item *item, char *page) 290 { 291 struct vkms_configfs_plane *plane; 292 enum drm_plane_type type; 293 294 plane = plane_item_to_vkms_configfs_plane(item); 295 296 scoped_guard(mutex, &plane->dev->lock) 297 type = vkms_config_plane_get_type(plane->config); 298 299 return sprintf(page, "%u", type); 300 } 301 302 static ssize_t plane_type_store(struct config_item *item, const char *page, 303 size_t count) 304 { 305 struct vkms_configfs_plane *plane; 306 enum drm_plane_type type; 307 308 plane = plane_item_to_vkms_configfs_plane(item); 309 310 if (kstrtouint(page, 10, &type)) 311 return -EINVAL; 312 313 if (type != DRM_PLANE_TYPE_OVERLAY && type != DRM_PLANE_TYPE_PRIMARY && 314 type != DRM_PLANE_TYPE_CURSOR) 315 return -EINVAL; 316 317 scoped_guard(mutex, &plane->dev->lock) { 318 if (plane->dev->enabled) 319 return -EBUSY; 320 321 vkms_config_plane_set_type(plane->config, type); 322 } 323 324 return (ssize_t)count; 325 } 326 327 CONFIGFS_ATTR(plane_, type); 328 329 static struct configfs_attribute *plane_item_attrs[] = { 330 &plane_attr_type, 331 NULL, 332 }; 333 334 static void plane_release(struct config_item *item) 335 { 336 struct vkms_configfs_plane *plane; 337 struct mutex *lock; 338 339 plane = plane_item_to_vkms_configfs_plane(item); 340 lock = &plane->dev->lock; 341 342 scoped_guard(mutex, lock) { 343 vkms_config_destroy_plane(plane->config); 344 kfree(plane); 345 } 346 } 347 348 static struct configfs_item_operations plane_item_operations = { 349 .release = &plane_release, 350 }; 351 352 static const struct config_item_type plane_item_type = { 353 .ct_attrs = plane_item_attrs, 354 .ct_item_ops = &plane_item_operations, 355 .ct_owner = THIS_MODULE, 356 }; 357 358 static struct config_group *make_plane_group(struct config_group *group, 359 const char *name) 360 { 361 struct vkms_configfs_device *dev; 362 struct vkms_configfs_plane *plane; 363 int ret; 364 365 dev = child_group_to_vkms_configfs_device(group); 366 367 scoped_guard(mutex, &dev->lock) { 368 if (dev->enabled) 369 return ERR_PTR(-EBUSY); 370 371 plane = kzalloc(sizeof(*plane), GFP_KERNEL); 372 if (!plane) 373 return ERR_PTR(-ENOMEM); 374 375 plane->dev = dev; 376 377 plane->config = vkms_config_create_plane(dev->config); 378 if (IS_ERR(plane->config)) { 379 ret = PTR_ERR(plane->config); 380 kfree(plane); 381 return ERR_PTR(ret); 382 } 383 384 config_group_init_type_name(&plane->group, name, &plane_item_type); 385 386 config_group_init_type_name(&plane->possible_crtcs_group, 387 "possible_crtcs", 388 &plane_possible_crtcs_group_type); 389 configfs_add_default_group(&plane->possible_crtcs_group, 390 &plane->group); 391 } 392 393 return &plane->group; 394 } 395 396 static struct configfs_group_operations planes_group_operations = { 397 .make_group = &make_plane_group, 398 }; 399 400 static const struct config_item_type plane_group_type = { 401 .ct_group_ops = &planes_group_operations, 402 .ct_owner = THIS_MODULE, 403 }; 404 405 static int encoder_possible_crtcs_allow_link(struct config_item *src, 406 struct config_item *target) 407 { 408 struct vkms_configfs_encoder *encoder; 409 struct vkms_configfs_crtc *crtc; 410 int ret; 411 412 if (target->ci_type != &crtc_item_type) 413 return -EINVAL; 414 415 encoder = encoder_possible_crtcs_item_to_vkms_configfs_encoder(src); 416 crtc = crtc_item_to_vkms_configfs_crtc(target); 417 418 scoped_guard(mutex, &encoder->dev->lock) { 419 if (encoder->dev->enabled) 420 return -EBUSY; 421 422 ret = vkms_config_encoder_attach_crtc(encoder->config, crtc->config); 423 } 424 425 return ret; 426 } 427 428 static void encoder_possible_crtcs_drop_link(struct config_item *src, 429 struct config_item *target) 430 { 431 struct vkms_configfs_encoder *encoder; 432 struct vkms_configfs_crtc *crtc; 433 434 encoder = encoder_possible_crtcs_item_to_vkms_configfs_encoder(src); 435 crtc = crtc_item_to_vkms_configfs_crtc(target); 436 437 scoped_guard(mutex, &encoder->dev->lock) 438 vkms_config_encoder_detach_crtc(encoder->config, crtc->config); 439 } 440 441 static struct configfs_item_operations encoder_possible_crtcs_item_operations = { 442 .allow_link = encoder_possible_crtcs_allow_link, 443 .drop_link = encoder_possible_crtcs_drop_link, 444 }; 445 446 static const struct config_item_type encoder_possible_crtcs_group_type = { 447 .ct_item_ops = &encoder_possible_crtcs_item_operations, 448 .ct_owner = THIS_MODULE, 449 }; 450 451 static void encoder_release(struct config_item *item) 452 { 453 struct vkms_configfs_encoder *encoder; 454 struct mutex *lock; 455 456 encoder = encoder_item_to_vkms_configfs_encoder(item); 457 lock = &encoder->dev->lock; 458 459 scoped_guard(mutex, lock) { 460 vkms_config_destroy_encoder(encoder->dev->config, encoder->config); 461 kfree(encoder); 462 } 463 } 464 465 static struct configfs_item_operations encoder_item_operations = { 466 .release = &encoder_release, 467 }; 468 469 static const struct config_item_type encoder_item_type = { 470 .ct_item_ops = &encoder_item_operations, 471 .ct_owner = THIS_MODULE, 472 }; 473 474 static struct config_group *make_encoder_group(struct config_group *group, 475 const char *name) 476 { 477 struct vkms_configfs_device *dev; 478 struct vkms_configfs_encoder *encoder; 479 int ret; 480 481 dev = child_group_to_vkms_configfs_device(group); 482 483 scoped_guard(mutex, &dev->lock) { 484 if (dev->enabled) 485 return ERR_PTR(-EBUSY); 486 487 encoder = kzalloc(sizeof(*encoder), GFP_KERNEL); 488 if (!encoder) 489 return ERR_PTR(-ENOMEM); 490 491 encoder->dev = dev; 492 493 encoder->config = vkms_config_create_encoder(dev->config); 494 if (IS_ERR(encoder->config)) { 495 ret = PTR_ERR(encoder->config); 496 kfree(encoder); 497 return ERR_PTR(ret); 498 } 499 500 config_group_init_type_name(&encoder->group, name, 501 &encoder_item_type); 502 503 config_group_init_type_name(&encoder->possible_crtcs_group, 504 "possible_crtcs", 505 &encoder_possible_crtcs_group_type); 506 configfs_add_default_group(&encoder->possible_crtcs_group, 507 &encoder->group); 508 } 509 510 return &encoder->group; 511 } 512 513 static struct configfs_group_operations encoders_group_operations = { 514 .make_group = &make_encoder_group, 515 }; 516 517 static const struct config_item_type encoder_group_type = { 518 .ct_group_ops = &encoders_group_operations, 519 .ct_owner = THIS_MODULE, 520 }; 521 522 static ssize_t connector_status_show(struct config_item *item, char *page) 523 { 524 struct vkms_configfs_connector *connector; 525 enum drm_connector_status status; 526 527 connector = connector_item_to_vkms_configfs_connector(item); 528 529 scoped_guard(mutex, &connector->dev->lock) 530 status = vkms_config_connector_get_status(connector->config); 531 532 return sprintf(page, "%u", status); 533 } 534 535 static ssize_t connector_status_store(struct config_item *item, 536 const char *page, size_t count) 537 { 538 struct vkms_configfs_connector *connector; 539 enum drm_connector_status status; 540 541 connector = connector_item_to_vkms_configfs_connector(item); 542 543 if (kstrtouint(page, 10, &status)) 544 return -EINVAL; 545 546 if (status != connector_status_connected && 547 status != connector_status_disconnected && 548 status != connector_status_unknown) 549 return -EINVAL; 550 551 scoped_guard(mutex, &connector->dev->lock) { 552 vkms_config_connector_set_status(connector->config, status); 553 554 if (connector->dev->enabled) 555 vkms_trigger_connector_hotplug(connector->dev->config->dev); 556 } 557 558 return (ssize_t)count; 559 } 560 561 CONFIGFS_ATTR(connector_, status); 562 563 static struct configfs_attribute *connector_item_attrs[] = { 564 &connector_attr_status, 565 NULL, 566 }; 567 568 static void connector_release(struct config_item *item) 569 { 570 struct vkms_configfs_connector *connector; 571 struct mutex *lock; 572 573 connector = connector_item_to_vkms_configfs_connector(item); 574 lock = &connector->dev->lock; 575 576 scoped_guard(mutex, lock) { 577 vkms_config_destroy_connector(connector->config); 578 kfree(connector); 579 } 580 } 581 582 static struct configfs_item_operations connector_item_operations = { 583 .release = &connector_release, 584 }; 585 586 static const struct config_item_type connector_item_type = { 587 .ct_attrs = connector_item_attrs, 588 .ct_item_ops = &connector_item_operations, 589 .ct_owner = THIS_MODULE, 590 }; 591 592 static int connector_possible_encoders_allow_link(struct config_item *src, 593 struct config_item *target) 594 { 595 struct vkms_configfs_connector *connector; 596 struct vkms_configfs_encoder *encoder; 597 int ret; 598 599 if (target->ci_type != &encoder_item_type) 600 return -EINVAL; 601 602 connector = connector_possible_encoders_item_to_vkms_configfs_connector(src); 603 encoder = encoder_item_to_vkms_configfs_encoder(target); 604 605 scoped_guard(mutex, &connector->dev->lock) { 606 if (connector->dev->enabled) 607 return -EBUSY; 608 609 ret = vkms_config_connector_attach_encoder(connector->config, 610 encoder->config); 611 } 612 613 return ret; 614 } 615 616 static void connector_possible_encoders_drop_link(struct config_item *src, 617 struct config_item *target) 618 { 619 struct vkms_configfs_connector *connector; 620 struct vkms_configfs_encoder *encoder; 621 622 connector = connector_possible_encoders_item_to_vkms_configfs_connector(src); 623 encoder = encoder_item_to_vkms_configfs_encoder(target); 624 625 scoped_guard(mutex, &connector->dev->lock) { 626 vkms_config_connector_detach_encoder(connector->config, 627 encoder->config); 628 } 629 } 630 631 static struct configfs_item_operations connector_possible_encoders_item_operations = { 632 .allow_link = connector_possible_encoders_allow_link, 633 .drop_link = connector_possible_encoders_drop_link, 634 }; 635 636 static const struct config_item_type connector_possible_encoders_group_type = { 637 .ct_item_ops = &connector_possible_encoders_item_operations, 638 .ct_owner = THIS_MODULE, 639 }; 640 641 static struct config_group *make_connector_group(struct config_group *group, 642 const char *name) 643 { 644 struct vkms_configfs_device *dev; 645 struct vkms_configfs_connector *connector; 646 int ret; 647 648 dev = child_group_to_vkms_configfs_device(group); 649 650 scoped_guard(mutex, &dev->lock) { 651 if (dev->enabled) 652 return ERR_PTR(-EBUSY); 653 654 connector = kzalloc(sizeof(*connector), GFP_KERNEL); 655 if (!connector) 656 return ERR_PTR(-ENOMEM); 657 658 connector->dev = dev; 659 660 connector->config = vkms_config_create_connector(dev->config); 661 if (IS_ERR(connector->config)) { 662 ret = PTR_ERR(connector->config); 663 kfree(connector); 664 return ERR_PTR(ret); 665 } 666 667 config_group_init_type_name(&connector->group, name, 668 &connector_item_type); 669 670 config_group_init_type_name(&connector->possible_encoders_group, 671 "possible_encoders", 672 &connector_possible_encoders_group_type); 673 configfs_add_default_group(&connector->possible_encoders_group, 674 &connector->group); 675 } 676 677 return &connector->group; 678 } 679 680 static struct configfs_group_operations connectors_group_operations = { 681 .make_group = &make_connector_group, 682 }; 683 684 static const struct config_item_type connector_group_type = { 685 .ct_group_ops = &connectors_group_operations, 686 .ct_owner = THIS_MODULE, 687 }; 688 689 static ssize_t device_enabled_show(struct config_item *item, char *page) 690 { 691 struct vkms_configfs_device *dev; 692 bool enabled; 693 694 dev = device_item_to_vkms_configfs_device(item); 695 696 scoped_guard(mutex, &dev->lock) 697 enabled = dev->enabled; 698 699 return sprintf(page, "%d\n", enabled); 700 } 701 702 static ssize_t device_enabled_store(struct config_item *item, const char *page, 703 size_t count) 704 { 705 struct vkms_configfs_device *dev; 706 bool enabled; 707 int ret = 0; 708 709 dev = device_item_to_vkms_configfs_device(item); 710 711 if (kstrtobool(page, &enabled)) 712 return -EINVAL; 713 714 scoped_guard(mutex, &dev->lock) { 715 if (!dev->enabled && enabled) { 716 if (!vkms_config_is_valid(dev->config)) 717 return -EINVAL; 718 719 ret = vkms_create(dev->config); 720 if (ret) 721 return ret; 722 } else if (dev->enabled && !enabled) { 723 vkms_destroy(dev->config); 724 } 725 726 dev->enabled = enabled; 727 } 728 729 return (ssize_t)count; 730 } 731 732 CONFIGFS_ATTR(device_, enabled); 733 734 static struct configfs_attribute *device_item_attrs[] = { 735 &device_attr_enabled, 736 NULL, 737 }; 738 739 static void device_release(struct config_item *item) 740 { 741 struct vkms_configfs_device *dev; 742 743 dev = device_item_to_vkms_configfs_device(item); 744 745 if (dev->enabled) 746 vkms_destroy(dev->config); 747 748 mutex_destroy(&dev->lock); 749 vkms_config_destroy(dev->config); 750 kfree(dev); 751 } 752 753 static struct configfs_item_operations device_item_operations = { 754 .release = &device_release, 755 }; 756 757 static const struct config_item_type device_item_type = { 758 .ct_attrs = device_item_attrs, 759 .ct_item_ops = &device_item_operations, 760 .ct_owner = THIS_MODULE, 761 }; 762 763 static struct config_group *make_device_group(struct config_group *group, 764 const char *name) 765 { 766 struct vkms_configfs_device *dev; 767 int ret; 768 769 if (strcmp(name, DEFAULT_DEVICE_NAME) == 0) 770 return ERR_PTR(-EINVAL); 771 772 dev = kzalloc(sizeof(*dev), GFP_KERNEL); 773 if (!dev) 774 return ERR_PTR(-ENOMEM); 775 776 dev->config = vkms_config_create(name); 777 if (IS_ERR(dev->config)) { 778 ret = PTR_ERR(dev->config); 779 kfree(dev); 780 return ERR_PTR(ret); 781 } 782 783 config_group_init_type_name(&dev->group, name, &device_item_type); 784 mutex_init(&dev->lock); 785 786 config_group_init_type_name(&dev->planes_group, "planes", 787 &plane_group_type); 788 configfs_add_default_group(&dev->planes_group, &dev->group); 789 790 config_group_init_type_name(&dev->crtcs_group, "crtcs", 791 &crtc_group_type); 792 configfs_add_default_group(&dev->crtcs_group, &dev->group); 793 794 config_group_init_type_name(&dev->encoders_group, "encoders", 795 &encoder_group_type); 796 configfs_add_default_group(&dev->encoders_group, &dev->group); 797 798 config_group_init_type_name(&dev->connectors_group, "connectors", 799 &connector_group_type); 800 configfs_add_default_group(&dev->connectors_group, &dev->group); 801 802 return &dev->group; 803 } 804 805 static struct configfs_group_operations device_group_ops = { 806 .make_group = &make_device_group, 807 }; 808 809 static const struct config_item_type device_group_type = { 810 .ct_group_ops = &device_group_ops, 811 .ct_owner = THIS_MODULE, 812 }; 813 814 static struct configfs_subsystem vkms_subsys = { 815 .su_group = { 816 .cg_item = { 817 .ci_name = "vkms", 818 .ci_type = &device_group_type, 819 }, 820 }, 821 .su_mutex = __MUTEX_INITIALIZER(vkms_subsys.su_mutex), 822 }; 823 824 int vkms_configfs_register(void) 825 { 826 int ret; 827 828 if (is_configfs_registered) 829 return 0; 830 831 config_group_init(&vkms_subsys.su_group); 832 ret = configfs_register_subsystem(&vkms_subsys); 833 834 is_configfs_registered = ret == 0; 835 836 return ret; 837 } 838 839 void vkms_configfs_unregister(void) 840 { 841 if (is_configfs_registered) 842 configfs_unregister_subsystem(&vkms_subsys); 843 } 844