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 367 return 0; 368 } 369 370 static const struct drm_debugfs_info vkms_config_debugfs_list[] = { 371 { "vkms_config", vkms_config_show, 0 }, 372 }; 373 374 void vkms_config_register_debugfs(struct vkms_device *vkms_device) 375 { 376 drm_debugfs_add_files(&vkms_device->drm, vkms_config_debugfs_list, 377 ARRAY_SIZE(vkms_config_debugfs_list)); 378 } 379 380 struct vkms_config_plane *vkms_config_create_plane(struct vkms_config *config) 381 { 382 struct vkms_config_plane *plane_cfg; 383 384 plane_cfg = kzalloc(sizeof(*plane_cfg), GFP_KERNEL); 385 if (!plane_cfg) 386 return ERR_PTR(-ENOMEM); 387 388 plane_cfg->config = config; 389 vkms_config_plane_set_type(plane_cfg, DRM_PLANE_TYPE_OVERLAY); 390 xa_init_flags(&plane_cfg->possible_crtcs, XA_FLAGS_ALLOC); 391 392 list_add_tail(&plane_cfg->link, &config->planes); 393 394 return plane_cfg; 395 } 396 EXPORT_SYMBOL_IF_KUNIT(vkms_config_create_plane); 397 398 void vkms_config_destroy_plane(struct vkms_config_plane *plane_cfg) 399 { 400 xa_destroy(&plane_cfg->possible_crtcs); 401 list_del(&plane_cfg->link); 402 kfree(plane_cfg); 403 } 404 EXPORT_SYMBOL_IF_KUNIT(vkms_config_destroy_plane); 405 406 int __must_check vkms_config_plane_attach_crtc(struct vkms_config_plane *plane_cfg, 407 struct vkms_config_crtc *crtc_cfg) 408 { 409 struct vkms_config_crtc *possible_crtc; 410 unsigned long idx = 0; 411 u32 crtc_idx = 0; 412 413 if (plane_cfg->config != crtc_cfg->config) 414 return -EINVAL; 415 416 vkms_config_plane_for_each_possible_crtc(plane_cfg, idx, possible_crtc) { 417 if (possible_crtc == crtc_cfg) 418 return -EEXIST; 419 } 420 421 return xa_alloc(&plane_cfg->possible_crtcs, &crtc_idx, crtc_cfg, 422 xa_limit_32b, GFP_KERNEL); 423 } 424 EXPORT_SYMBOL_IF_KUNIT(vkms_config_plane_attach_crtc); 425 426 void vkms_config_plane_detach_crtc(struct vkms_config_plane *plane_cfg, 427 struct vkms_config_crtc *crtc_cfg) 428 { 429 struct vkms_config_crtc *possible_crtc; 430 unsigned long idx = 0; 431 432 vkms_config_plane_for_each_possible_crtc(plane_cfg, idx, possible_crtc) { 433 if (possible_crtc == crtc_cfg) 434 xa_erase(&plane_cfg->possible_crtcs, idx); 435 } 436 } 437 EXPORT_SYMBOL_IF_KUNIT(vkms_config_plane_detach_crtc); 438 439 struct vkms_config_crtc *vkms_config_create_crtc(struct vkms_config *config) 440 { 441 struct vkms_config_crtc *crtc_cfg; 442 443 crtc_cfg = kzalloc(sizeof(*crtc_cfg), GFP_KERNEL); 444 if (!crtc_cfg) 445 return ERR_PTR(-ENOMEM); 446 447 crtc_cfg->config = config; 448 vkms_config_crtc_set_writeback(crtc_cfg, false); 449 450 list_add_tail(&crtc_cfg->link, &config->crtcs); 451 452 return crtc_cfg; 453 } 454 EXPORT_SYMBOL_IF_KUNIT(vkms_config_create_crtc); 455 456 void vkms_config_destroy_crtc(struct vkms_config *config, 457 struct vkms_config_crtc *crtc_cfg) 458 { 459 struct vkms_config_plane *plane_cfg; 460 struct vkms_config_encoder *encoder_cfg; 461 462 vkms_config_for_each_plane(config, plane_cfg) 463 vkms_config_plane_detach_crtc(plane_cfg, crtc_cfg); 464 465 vkms_config_for_each_encoder(config, encoder_cfg) 466 vkms_config_encoder_detach_crtc(encoder_cfg, crtc_cfg); 467 468 list_del(&crtc_cfg->link); 469 kfree(crtc_cfg); 470 } 471 EXPORT_SYMBOL_IF_KUNIT(vkms_config_destroy_crtc); 472 473 /** 474 * vkms_config_crtc_get_plane() - Return the first attached plane to a CRTC with 475 * the specific type 476 * @config: Configuration containing the CRTC and the plane 477 * @crtc_cfg: Only find planes attached to this CRTC 478 * @type: Plane type to search 479 * 480 * Returns: 481 * The first plane found attached to @crtc_cfg with the type @type. 482 */ 483 static struct vkms_config_plane *vkms_config_crtc_get_plane(const struct vkms_config *config, 484 struct vkms_config_crtc *crtc_cfg, 485 enum drm_plane_type type) 486 { 487 struct vkms_config_plane *plane_cfg; 488 struct vkms_config_crtc *possible_crtc; 489 enum drm_plane_type current_type; 490 unsigned long idx = 0; 491 492 vkms_config_for_each_plane(config, plane_cfg) { 493 current_type = vkms_config_plane_get_type(plane_cfg); 494 495 vkms_config_plane_for_each_possible_crtc(plane_cfg, idx, possible_crtc) { 496 if (possible_crtc == crtc_cfg && current_type == type) 497 return plane_cfg; 498 } 499 } 500 501 return NULL; 502 } 503 504 struct vkms_config_plane *vkms_config_crtc_primary_plane(const struct vkms_config *config, 505 struct vkms_config_crtc *crtc_cfg) 506 { 507 return vkms_config_crtc_get_plane(config, crtc_cfg, DRM_PLANE_TYPE_PRIMARY); 508 } 509 EXPORT_SYMBOL_IF_KUNIT(vkms_config_crtc_primary_plane); 510 511 struct vkms_config_plane *vkms_config_crtc_cursor_plane(const struct vkms_config *config, 512 struct vkms_config_crtc *crtc_cfg) 513 { 514 return vkms_config_crtc_get_plane(config, crtc_cfg, DRM_PLANE_TYPE_CURSOR); 515 } 516 EXPORT_SYMBOL_IF_KUNIT(vkms_config_crtc_cursor_plane); 517 518 struct vkms_config_encoder *vkms_config_create_encoder(struct vkms_config *config) 519 { 520 struct vkms_config_encoder *encoder_cfg; 521 522 encoder_cfg = kzalloc(sizeof(*encoder_cfg), GFP_KERNEL); 523 if (!encoder_cfg) 524 return ERR_PTR(-ENOMEM); 525 526 encoder_cfg->config = config; 527 xa_init_flags(&encoder_cfg->possible_crtcs, XA_FLAGS_ALLOC); 528 529 list_add_tail(&encoder_cfg->link, &config->encoders); 530 531 return encoder_cfg; 532 } 533 EXPORT_SYMBOL_IF_KUNIT(vkms_config_create_encoder); 534 535 void vkms_config_destroy_encoder(struct vkms_config *config, 536 struct vkms_config_encoder *encoder_cfg) 537 { 538 struct vkms_config_connector *connector_cfg; 539 540 vkms_config_for_each_connector(config, connector_cfg) 541 vkms_config_connector_detach_encoder(connector_cfg, encoder_cfg); 542 543 xa_destroy(&encoder_cfg->possible_crtcs); 544 list_del(&encoder_cfg->link); 545 kfree(encoder_cfg); 546 } 547 EXPORT_SYMBOL_IF_KUNIT(vkms_config_destroy_encoder); 548 549 int __must_check vkms_config_encoder_attach_crtc(struct vkms_config_encoder *encoder_cfg, 550 struct vkms_config_crtc *crtc_cfg) 551 { 552 struct vkms_config_crtc *possible_crtc; 553 unsigned long idx = 0; 554 u32 crtc_idx = 0; 555 556 if (encoder_cfg->config != crtc_cfg->config) 557 return -EINVAL; 558 559 vkms_config_encoder_for_each_possible_crtc(encoder_cfg, idx, possible_crtc) { 560 if (possible_crtc == crtc_cfg) 561 return -EEXIST; 562 } 563 564 return xa_alloc(&encoder_cfg->possible_crtcs, &crtc_idx, crtc_cfg, 565 xa_limit_32b, GFP_KERNEL); 566 } 567 EXPORT_SYMBOL_IF_KUNIT(vkms_config_encoder_attach_crtc); 568 569 void vkms_config_encoder_detach_crtc(struct vkms_config_encoder *encoder_cfg, 570 struct vkms_config_crtc *crtc_cfg) 571 { 572 struct vkms_config_crtc *possible_crtc; 573 unsigned long idx = 0; 574 575 vkms_config_encoder_for_each_possible_crtc(encoder_cfg, idx, possible_crtc) { 576 if (possible_crtc == crtc_cfg) 577 xa_erase(&encoder_cfg->possible_crtcs, idx); 578 } 579 } 580 EXPORT_SYMBOL_IF_KUNIT(vkms_config_encoder_detach_crtc); 581 582 struct vkms_config_connector *vkms_config_create_connector(struct vkms_config *config) 583 { 584 struct vkms_config_connector *connector_cfg; 585 586 connector_cfg = kzalloc(sizeof(*connector_cfg), GFP_KERNEL); 587 if (!connector_cfg) 588 return ERR_PTR(-ENOMEM); 589 590 connector_cfg->config = config; 591 xa_init_flags(&connector_cfg->possible_encoders, XA_FLAGS_ALLOC); 592 593 list_add_tail(&connector_cfg->link, &config->connectors); 594 595 return connector_cfg; 596 } 597 EXPORT_SYMBOL_IF_KUNIT(vkms_config_create_connector); 598 599 void vkms_config_destroy_connector(struct vkms_config_connector *connector_cfg) 600 { 601 xa_destroy(&connector_cfg->possible_encoders); 602 list_del(&connector_cfg->link); 603 kfree(connector_cfg); 604 } 605 EXPORT_SYMBOL_IF_KUNIT(vkms_config_destroy_connector); 606 607 int __must_check vkms_config_connector_attach_encoder(struct vkms_config_connector *connector_cfg, 608 struct vkms_config_encoder *encoder_cfg) 609 { 610 struct vkms_config_encoder *possible_encoder; 611 unsigned long idx = 0; 612 u32 encoder_idx = 0; 613 614 if (connector_cfg->config != encoder_cfg->config) 615 return -EINVAL; 616 617 vkms_config_connector_for_each_possible_encoder(connector_cfg, idx, 618 possible_encoder) { 619 if (possible_encoder == encoder_cfg) 620 return -EEXIST; 621 } 622 623 return xa_alloc(&connector_cfg->possible_encoders, &encoder_idx, 624 encoder_cfg, xa_limit_32b, GFP_KERNEL); 625 } 626 EXPORT_SYMBOL_IF_KUNIT(vkms_config_connector_attach_encoder); 627 628 void vkms_config_connector_detach_encoder(struct vkms_config_connector *connector_cfg, 629 struct vkms_config_encoder *encoder_cfg) 630 { 631 struct vkms_config_encoder *possible_encoder; 632 unsigned long idx = 0; 633 634 vkms_config_connector_for_each_possible_encoder(connector_cfg, idx, 635 possible_encoder) { 636 if (possible_encoder == encoder_cfg) 637 xa_erase(&connector_cfg->possible_encoders, idx); 638 } 639 } 640 EXPORT_SYMBOL_IF_KUNIT(vkms_config_connector_detach_encoder); 641