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