1 // SPDX-License-Identifier: GPL-2.0+ 2 3 #include <linux/slab.h> 4 5 #include <drm/drm_print.h> 6 #include <drm/drm_debugfs.h> 7 #include <kunit/visibility.h> 8 9 #include "vkms_config.h" 10 11 struct vkms_config *vkms_config_create(const char *dev_name) 12 { 13 struct vkms_config *config; 14 15 config = kzalloc(sizeof(*config), GFP_KERNEL); 16 if (!config) 17 return ERR_PTR(-ENOMEM); 18 19 config->dev_name = kstrdup_const(dev_name, GFP_KERNEL); 20 if (!config->dev_name) { 21 kfree(config); 22 return ERR_PTR(-ENOMEM); 23 } 24 25 INIT_LIST_HEAD(&config->planes); 26 INIT_LIST_HEAD(&config->crtcs); 27 INIT_LIST_HEAD(&config->encoders); 28 INIT_LIST_HEAD(&config->connectors); 29 30 return config; 31 } 32 EXPORT_SYMBOL_IF_KUNIT(vkms_config_create); 33 34 struct vkms_config *vkms_config_default_create(bool enable_cursor, 35 bool enable_writeback, 36 bool enable_overlay) 37 { 38 struct vkms_config *config; 39 struct vkms_config_plane *plane_cfg; 40 struct vkms_config_crtc *crtc_cfg; 41 struct vkms_config_encoder *encoder_cfg; 42 struct vkms_config_connector *connector_cfg; 43 int n; 44 45 config = vkms_config_create(DEFAULT_DEVICE_NAME); 46 if (IS_ERR(config)) 47 return config; 48 49 plane_cfg = vkms_config_create_plane(config); 50 if (IS_ERR(plane_cfg)) 51 goto err_alloc; 52 vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_PRIMARY); 53 54 crtc_cfg = vkms_config_create_crtc(config); 55 if (IS_ERR(crtc_cfg)) 56 goto err_alloc; 57 vkms_config_crtc_set_writeback(crtc_cfg, enable_writeback); 58 59 if (vkms_config_plane_attach_crtc(plane_cfg, crtc_cfg)) 60 goto err_alloc; 61 62 if (enable_overlay) { 63 for (n = 0; n < NUM_OVERLAY_PLANES; n++) { 64 plane_cfg = vkms_config_create_plane(config); 65 if (IS_ERR(plane_cfg)) 66 goto err_alloc; 67 68 vkms_config_plane_set_type(plane_cfg, 69 DRM_PLANE_TYPE_OVERLAY); 70 71 if (vkms_config_plane_attach_crtc(plane_cfg, crtc_cfg)) 72 goto err_alloc; 73 } 74 } 75 76 if (enable_cursor) { 77 plane_cfg = vkms_config_create_plane(config); 78 if (IS_ERR(plane_cfg)) 79 goto err_alloc; 80 81 vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_CURSOR); 82 83 if (vkms_config_plane_attach_crtc(plane_cfg, crtc_cfg)) 84 goto err_alloc; 85 } 86 87 encoder_cfg = vkms_config_create_encoder(config); 88 if (IS_ERR(encoder_cfg)) 89 goto err_alloc; 90 91 if (vkms_config_encoder_attach_crtc(encoder_cfg, crtc_cfg)) 92 goto err_alloc; 93 94 connector_cfg = vkms_config_create_connector(config); 95 if (IS_ERR(connector_cfg)) 96 goto err_alloc; 97 98 if (vkms_config_connector_attach_encoder(connector_cfg, encoder_cfg)) 99 goto err_alloc; 100 101 return config; 102 103 err_alloc: 104 vkms_config_destroy(config); 105 return ERR_PTR(-ENOMEM); 106 } 107 EXPORT_SYMBOL_IF_KUNIT(vkms_config_default_create); 108 109 void vkms_config_destroy(struct vkms_config *config) 110 { 111 struct vkms_config_plane *plane_cfg, *plane_tmp; 112 struct vkms_config_crtc *crtc_cfg, *crtc_tmp; 113 struct vkms_config_encoder *encoder_cfg, *encoder_tmp; 114 struct vkms_config_connector *connector_cfg, *connector_tmp; 115 116 list_for_each_entry_safe(plane_cfg, plane_tmp, &config->planes, link) 117 vkms_config_destroy_plane(plane_cfg); 118 119 list_for_each_entry_safe(crtc_cfg, crtc_tmp, &config->crtcs, link) 120 vkms_config_destroy_crtc(config, crtc_cfg); 121 122 list_for_each_entry_safe(encoder_cfg, encoder_tmp, &config->encoders, link) 123 vkms_config_destroy_encoder(config, encoder_cfg); 124 125 list_for_each_entry_safe(connector_cfg, connector_tmp, &config->connectors, link) 126 vkms_config_destroy_connector(connector_cfg); 127 128 kfree_const(config->dev_name); 129 kfree(config); 130 } 131 EXPORT_SYMBOL_IF_KUNIT(vkms_config_destroy); 132 133 static bool valid_plane_number(const struct vkms_config *config) 134 { 135 struct drm_device *dev = config->dev ? &config->dev->drm : NULL; 136 size_t n_planes; 137 138 n_planes = list_count_nodes((struct list_head *)&config->planes); 139 if (n_planes <= 0 || n_planes >= 32) { 140 drm_info(dev, "The number of planes must be between 1 and 31\n"); 141 return false; 142 } 143 144 return true; 145 } 146 147 static bool valid_planes_for_crtc(const struct vkms_config *config, 148 struct vkms_config_crtc *crtc_cfg) 149 { 150 struct drm_device *dev = config->dev ? &config->dev->drm : NULL; 151 struct vkms_config_plane *plane_cfg; 152 bool has_primary_plane = false; 153 bool has_cursor_plane = false; 154 155 vkms_config_for_each_plane(config, plane_cfg) { 156 struct vkms_config_crtc *possible_crtc; 157 unsigned long idx = 0; 158 enum drm_plane_type type; 159 160 type = vkms_config_plane_get_type(plane_cfg); 161 162 vkms_config_plane_for_each_possible_crtc(plane_cfg, idx, possible_crtc) { 163 if (possible_crtc != crtc_cfg) 164 continue; 165 166 if (type == DRM_PLANE_TYPE_PRIMARY) { 167 if (has_primary_plane) { 168 drm_info(dev, "Multiple primary planes\n"); 169 return false; 170 } 171 172 has_primary_plane = true; 173 } else if (type == DRM_PLANE_TYPE_CURSOR) { 174 if (has_cursor_plane) { 175 drm_info(dev, "Multiple cursor planes\n"); 176 return false; 177 } 178 179 has_cursor_plane = true; 180 } 181 } 182 } 183 184 if (!has_primary_plane) { 185 drm_info(dev, "Primary plane not found\n"); 186 return false; 187 } 188 189 return true; 190 } 191 192 static bool valid_plane_possible_crtcs(const struct vkms_config *config) 193 { 194 struct drm_device *dev = config->dev ? &config->dev->drm : NULL; 195 struct vkms_config_plane *plane_cfg; 196 197 vkms_config_for_each_plane(config, plane_cfg) { 198 if (xa_empty(&plane_cfg->possible_crtcs)) { 199 drm_info(dev, "All planes must have at least one possible CRTC\n"); 200 return false; 201 } 202 } 203 204 return true; 205 } 206 207 static bool valid_crtc_number(const struct vkms_config *config) 208 { 209 struct drm_device *dev = config->dev ? &config->dev->drm : NULL; 210 size_t n_crtcs; 211 212 n_crtcs = list_count_nodes((struct list_head *)&config->crtcs); 213 if (n_crtcs <= 0 || n_crtcs >= 32) { 214 drm_info(dev, "The number of CRTCs must be between 1 and 31\n"); 215 return false; 216 } 217 218 return true; 219 } 220 221 static bool valid_encoder_number(const struct vkms_config *config) 222 { 223 struct drm_device *dev = config->dev ? &config->dev->drm : NULL; 224 size_t n_encoders; 225 226 n_encoders = list_count_nodes((struct list_head *)&config->encoders); 227 if (n_encoders <= 0 || n_encoders >= 32) { 228 drm_info(dev, "The number of encoders must be between 1 and 31\n"); 229 return false; 230 } 231 232 return true; 233 } 234 235 static bool valid_encoder_possible_crtcs(const struct vkms_config *config) 236 { 237 struct drm_device *dev = config->dev ? &config->dev->drm : NULL; 238 struct vkms_config_crtc *crtc_cfg; 239 struct vkms_config_encoder *encoder_cfg; 240 241 vkms_config_for_each_encoder(config, encoder_cfg) { 242 if (xa_empty(&encoder_cfg->possible_crtcs)) { 243 drm_info(dev, "All encoders must have at least one possible CRTC\n"); 244 return false; 245 } 246 } 247 248 vkms_config_for_each_crtc(config, crtc_cfg) { 249 bool crtc_has_encoder = false; 250 251 vkms_config_for_each_encoder(config, encoder_cfg) { 252 struct vkms_config_crtc *possible_crtc; 253 unsigned long idx = 0; 254 255 vkms_config_encoder_for_each_possible_crtc(encoder_cfg, 256 idx, possible_crtc) { 257 if (possible_crtc == crtc_cfg) 258 crtc_has_encoder = true; 259 } 260 } 261 262 if (!crtc_has_encoder) { 263 drm_info(dev, "All CRTCs must have at least one possible encoder\n"); 264 return false; 265 } 266 } 267 268 return true; 269 } 270 271 static bool valid_connector_number(const struct vkms_config *config) 272 { 273 struct drm_device *dev = config->dev ? &config->dev->drm : NULL; 274 size_t n_connectors; 275 276 n_connectors = list_count_nodes((struct list_head *)&config->connectors); 277 if (n_connectors <= 0 || n_connectors >= 32) { 278 drm_info(dev, "The number of connectors must be between 1 and 31\n"); 279 return false; 280 } 281 282 return true; 283 } 284 285 static bool valid_connector_possible_encoders(const struct vkms_config *config) 286 { 287 struct drm_device *dev = config->dev ? &config->dev->drm : NULL; 288 struct vkms_config_connector *connector_cfg; 289 290 vkms_config_for_each_connector(config, connector_cfg) { 291 if (xa_empty(&connector_cfg->possible_encoders)) { 292 drm_info(dev, 293 "All connectors must have at least one possible encoder\n"); 294 return false; 295 } 296 } 297 298 return true; 299 } 300 301 bool vkms_config_is_valid(const struct vkms_config *config) 302 { 303 struct vkms_config_crtc *crtc_cfg; 304 305 if (!valid_plane_number(config)) 306 return false; 307 308 if (!valid_crtc_number(config)) 309 return false; 310 311 if (!valid_encoder_number(config)) 312 return false; 313 314 if (!valid_connector_number(config)) 315 return false; 316 317 if (!valid_plane_possible_crtcs(config)) 318 return false; 319 320 vkms_config_for_each_crtc(config, crtc_cfg) { 321 if (!valid_planes_for_crtc(config, crtc_cfg)) 322 return false; 323 } 324 325 if (!valid_encoder_possible_crtcs(config)) 326 return false; 327 328 if (!valid_connector_possible_encoders(config)) 329 return false; 330 331 return true; 332 } 333 EXPORT_SYMBOL_IF_KUNIT(vkms_config_is_valid); 334 335 static int vkms_config_show(struct seq_file *m, void *data) 336 { 337 struct drm_debugfs_entry *entry = m->private; 338 struct drm_device *dev = entry->dev; 339 struct vkms_device *vkmsdev = drm_device_to_vkms_device(dev); 340 const char *dev_name; 341 struct vkms_config_plane *plane_cfg; 342 struct vkms_config_crtc *crtc_cfg; 343 struct vkms_config_encoder *encoder_cfg; 344 struct vkms_config_connector *connector_cfg; 345 346 dev_name = vkms_config_get_device_name((struct vkms_config *)vkmsdev->config); 347 seq_printf(m, "dev_name=%s\n", dev_name); 348 349 vkms_config_for_each_plane(vkmsdev->config, plane_cfg) { 350 seq_puts(m, "plane:\n"); 351 seq_printf(m, "\ttype=%d\n", 352 vkms_config_plane_get_type(plane_cfg)); 353 } 354 355 vkms_config_for_each_crtc(vkmsdev->config, crtc_cfg) { 356 seq_puts(m, "crtc:\n"); 357 seq_printf(m, "\twriteback=%d\n", 358 vkms_config_crtc_get_writeback(crtc_cfg)); 359 } 360 361 vkms_config_for_each_encoder(vkmsdev->config, encoder_cfg) 362 seq_puts(m, "encoder\n"); 363 364 vkms_config_for_each_connector(vkmsdev->config, connector_cfg) { 365 seq_puts(m, "connector:\n"); 366 seq_printf(m, "\tstatus=%d\n", 367 vkms_config_connector_get_status(connector_cfg)); 368 } 369 370 return 0; 371 } 372 373 static const struct drm_debugfs_info vkms_config_debugfs_list[] = { 374 { "vkms_config", vkms_config_show, 0 }, 375 }; 376 377 void vkms_config_register_debugfs(struct vkms_device *vkms_device) 378 { 379 drm_debugfs_add_files(&vkms_device->drm, vkms_config_debugfs_list, 380 ARRAY_SIZE(vkms_config_debugfs_list)); 381 } 382 383 struct vkms_config_plane *vkms_config_create_plane(struct vkms_config *config) 384 { 385 struct vkms_config_plane *plane_cfg; 386 387 plane_cfg = kzalloc(sizeof(*plane_cfg), GFP_KERNEL); 388 if (!plane_cfg) 389 return ERR_PTR(-ENOMEM); 390 391 plane_cfg->config = config; 392 vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_OVERLAY); 393 xa_init_flags(&plane_cfg->possible_crtcs, XA_FLAGS_ALLOC); 394 395 list_add_tail(&plane_cfg->link, &config->planes); 396 397 return plane_cfg; 398 } 399 EXPORT_SYMBOL_IF_KUNIT(vkms_config_create_plane); 400 401 void vkms_config_destroy_plane(struct vkms_config_plane *plane_cfg) 402 { 403 xa_destroy(&plane_cfg->possible_crtcs); 404 list_del(&plane_cfg->link); 405 kfree(plane_cfg); 406 } 407 EXPORT_SYMBOL_IF_KUNIT(vkms_config_destroy_plane); 408 409 int __must_check vkms_config_plane_attach_crtc(struct vkms_config_plane *plane_cfg, 410 struct vkms_config_crtc *crtc_cfg) 411 { 412 struct vkms_config_crtc *possible_crtc; 413 unsigned long idx = 0; 414 u32 crtc_idx = 0; 415 416 if (plane_cfg->config != crtc_cfg->config) 417 return -EINVAL; 418 419 vkms_config_plane_for_each_possible_crtc(plane_cfg, idx, possible_crtc) { 420 if (possible_crtc == crtc_cfg) 421 return -EEXIST; 422 } 423 424 return xa_alloc(&plane_cfg->possible_crtcs, &crtc_idx, crtc_cfg, 425 xa_limit_32b, GFP_KERNEL); 426 } 427 EXPORT_SYMBOL_IF_KUNIT(vkms_config_plane_attach_crtc); 428 429 void vkms_config_plane_detach_crtc(struct vkms_config_plane *plane_cfg, 430 struct vkms_config_crtc *crtc_cfg) 431 { 432 struct vkms_config_crtc *possible_crtc; 433 unsigned long idx = 0; 434 435 vkms_config_plane_for_each_possible_crtc(plane_cfg, idx, possible_crtc) { 436 if (possible_crtc == crtc_cfg) 437 xa_erase(&plane_cfg->possible_crtcs, idx); 438 } 439 } 440 EXPORT_SYMBOL_IF_KUNIT(vkms_config_plane_detach_crtc); 441 442 struct vkms_config_crtc *vkms_config_create_crtc(struct vkms_config *config) 443 { 444 struct vkms_config_crtc *crtc_cfg; 445 446 crtc_cfg = kzalloc(sizeof(*crtc_cfg), GFP_KERNEL); 447 if (!crtc_cfg) 448 return ERR_PTR(-ENOMEM); 449 450 crtc_cfg->config = config; 451 vkms_config_crtc_set_writeback(crtc_cfg, false); 452 453 list_add_tail(&crtc_cfg->link, &config->crtcs); 454 455 return crtc_cfg; 456 } 457 EXPORT_SYMBOL_IF_KUNIT(vkms_config_create_crtc); 458 459 void vkms_config_destroy_crtc(struct vkms_config *config, 460 struct vkms_config_crtc *crtc_cfg) 461 { 462 struct vkms_config_plane *plane_cfg; 463 struct vkms_config_encoder *encoder_cfg; 464 465 vkms_config_for_each_plane(config, plane_cfg) 466 vkms_config_plane_detach_crtc(plane_cfg, crtc_cfg); 467 468 vkms_config_for_each_encoder(config, encoder_cfg) 469 vkms_config_encoder_detach_crtc(encoder_cfg, crtc_cfg); 470 471 list_del(&crtc_cfg->link); 472 kfree(crtc_cfg); 473 } 474 EXPORT_SYMBOL_IF_KUNIT(vkms_config_destroy_crtc); 475 476 /** 477 * vkms_config_crtc_get_plane() - Return the first attached plane to a CRTC with 478 * the specific type 479 * @config: Configuration containing the CRTC and the plane 480 * @crtc_cfg: Only find planes attached to this CRTC 481 * @type: Plane type to search 482 * 483 * Returns: 484 * The first plane found attached to @crtc_cfg with the type @type. 485 */ 486 static struct vkms_config_plane *vkms_config_crtc_get_plane(const struct vkms_config *config, 487 struct vkms_config_crtc *crtc_cfg, 488 enum drm_plane_type type) 489 { 490 struct vkms_config_plane *plane_cfg; 491 struct vkms_config_crtc *possible_crtc; 492 enum drm_plane_type current_type; 493 unsigned long idx = 0; 494 495 vkms_config_for_each_plane(config, plane_cfg) { 496 current_type = vkms_config_plane_get_type(plane_cfg); 497 498 vkms_config_plane_for_each_possible_crtc(plane_cfg, idx, possible_crtc) { 499 if (possible_crtc == crtc_cfg && current_type == type) 500 return plane_cfg; 501 } 502 } 503 504 return NULL; 505 } 506 507 struct vkms_config_plane *vkms_config_crtc_primary_plane(const struct vkms_config *config, 508 struct vkms_config_crtc *crtc_cfg) 509 { 510 return vkms_config_crtc_get_plane(config, crtc_cfg, DRM_PLANE_TYPE_PRIMARY); 511 } 512 EXPORT_SYMBOL_IF_KUNIT(vkms_config_crtc_primary_plane); 513 514 struct vkms_config_plane *vkms_config_crtc_cursor_plane(const struct vkms_config *config, 515 struct vkms_config_crtc *crtc_cfg) 516 { 517 return vkms_config_crtc_get_plane(config, crtc_cfg, DRM_PLANE_TYPE_CURSOR); 518 } 519 EXPORT_SYMBOL_IF_KUNIT(vkms_config_crtc_cursor_plane); 520 521 struct vkms_config_encoder *vkms_config_create_encoder(struct vkms_config *config) 522 { 523 struct vkms_config_encoder *encoder_cfg; 524 525 encoder_cfg = kzalloc(sizeof(*encoder_cfg), GFP_KERNEL); 526 if (!encoder_cfg) 527 return ERR_PTR(-ENOMEM); 528 529 encoder_cfg->config = config; 530 xa_init_flags(&encoder_cfg->possible_crtcs, XA_FLAGS_ALLOC); 531 532 list_add_tail(&encoder_cfg->link, &config->encoders); 533 534 return encoder_cfg; 535 } 536 EXPORT_SYMBOL_IF_KUNIT(vkms_config_create_encoder); 537 538 void vkms_config_destroy_encoder(struct vkms_config *config, 539 struct vkms_config_encoder *encoder_cfg) 540 { 541 struct vkms_config_connector *connector_cfg; 542 543 vkms_config_for_each_connector(config, connector_cfg) 544 vkms_config_connector_detach_encoder(connector_cfg, encoder_cfg); 545 546 xa_destroy(&encoder_cfg->possible_crtcs); 547 list_del(&encoder_cfg->link); 548 kfree(encoder_cfg); 549 } 550 EXPORT_SYMBOL_IF_KUNIT(vkms_config_destroy_encoder); 551 552 int __must_check vkms_config_encoder_attach_crtc(struct vkms_config_encoder *encoder_cfg, 553 struct vkms_config_crtc *crtc_cfg) 554 { 555 struct vkms_config_crtc *possible_crtc; 556 unsigned long idx = 0; 557 u32 crtc_idx = 0; 558 559 if (encoder_cfg->config != crtc_cfg->config) 560 return -EINVAL; 561 562 vkms_config_encoder_for_each_possible_crtc(encoder_cfg, idx, possible_crtc) { 563 if (possible_crtc == crtc_cfg) 564 return -EEXIST; 565 } 566 567 return xa_alloc(&encoder_cfg->possible_crtcs, &crtc_idx, crtc_cfg, 568 xa_limit_32b, GFP_KERNEL); 569 } 570 EXPORT_SYMBOL_IF_KUNIT(vkms_config_encoder_attach_crtc); 571 572 void vkms_config_encoder_detach_crtc(struct vkms_config_encoder *encoder_cfg, 573 struct vkms_config_crtc *crtc_cfg) 574 { 575 struct vkms_config_crtc *possible_crtc; 576 unsigned long idx = 0; 577 578 vkms_config_encoder_for_each_possible_crtc(encoder_cfg, idx, possible_crtc) { 579 if (possible_crtc == crtc_cfg) 580 xa_erase(&encoder_cfg->possible_crtcs, idx); 581 } 582 } 583 EXPORT_SYMBOL_IF_KUNIT(vkms_config_encoder_detach_crtc); 584 585 struct vkms_config_connector *vkms_config_create_connector(struct vkms_config *config) 586 { 587 struct vkms_config_connector *connector_cfg; 588 589 connector_cfg = kzalloc(sizeof(*connector_cfg), GFP_KERNEL); 590 if (!connector_cfg) 591 return ERR_PTR(-ENOMEM); 592 593 connector_cfg->config = config; 594 connector_cfg->status = connector_status_connected; 595 xa_init_flags(&connector_cfg->possible_encoders, XA_FLAGS_ALLOC); 596 597 list_add_tail(&connector_cfg->link, &config->connectors); 598 599 return connector_cfg; 600 } 601 EXPORT_SYMBOL_IF_KUNIT(vkms_config_create_connector); 602 603 void vkms_config_destroy_connector(struct vkms_config_connector *connector_cfg) 604 { 605 xa_destroy(&connector_cfg->possible_encoders); 606 list_del(&connector_cfg->link); 607 kfree(connector_cfg); 608 } 609 EXPORT_SYMBOL_IF_KUNIT(vkms_config_destroy_connector); 610 611 int __must_check vkms_config_connector_attach_encoder(struct vkms_config_connector *connector_cfg, 612 struct vkms_config_encoder *encoder_cfg) 613 { 614 struct vkms_config_encoder *possible_encoder; 615 unsigned long idx = 0; 616 u32 encoder_idx = 0; 617 618 if (connector_cfg->config != encoder_cfg->config) 619 return -EINVAL; 620 621 vkms_config_connector_for_each_possible_encoder(connector_cfg, idx, 622 possible_encoder) { 623 if (possible_encoder == encoder_cfg) 624 return -EEXIST; 625 } 626 627 return xa_alloc(&connector_cfg->possible_encoders, &encoder_idx, 628 encoder_cfg, xa_limit_32b, GFP_KERNEL); 629 } 630 EXPORT_SYMBOL_IF_KUNIT(vkms_config_connector_attach_encoder); 631 632 void vkms_config_connector_detach_encoder(struct vkms_config_connector *connector_cfg, 633 struct vkms_config_encoder *encoder_cfg) 634 { 635 struct vkms_config_encoder *possible_encoder; 636 unsigned long idx = 0; 637 638 vkms_config_connector_for_each_possible_encoder(connector_cfg, idx, 639 possible_encoder) { 640 if (possible_encoder == encoder_cfg) 641 xa_erase(&connector_cfg->possible_encoders, idx); 642 } 643 } 644 EXPORT_SYMBOL_IF_KUNIT(vkms_config_connector_detach_encoder); 645