1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2015-2018 Etnaviv Project 4 */ 5 6 #include <linux/component.h> 7 #include <linux/dma-mapping.h> 8 #include <linux/module.h> 9 #include <linux/of.h> 10 #include <linux/of_device.h> 11 #include <linux/platform_device.h> 12 #include <linux/uaccess.h> 13 14 #include <drm/drm_debugfs.h> 15 #include <drm/drm_drv.h> 16 #include <drm/drm_file.h> 17 #include <drm/drm_ioctl.h> 18 #include <drm/drm_of.h> 19 #include <drm/drm_prime.h> 20 #include <drm/drm_print.h> 21 22 #include "etnaviv_cmdbuf.h" 23 #include "etnaviv_drv.h" 24 #include "etnaviv_gpu.h" 25 #include "etnaviv_gem.h" 26 #include "etnaviv_mmu.h" 27 #include "etnaviv_perfmon.h" 28 29 /* 30 * DRM operations: 31 */ 32 33 static struct device_node *etnaviv_of_first_available_node(void) 34 { 35 struct device_node *np; 36 37 for_each_compatible_node(np, NULL, "vivante,gc") { 38 if (of_device_is_available(np)) 39 return np; 40 } 41 42 return NULL; 43 } 44 45 static void load_gpu(struct drm_device *dev) 46 { 47 struct etnaviv_drm_private *priv = dev->dev_private; 48 unsigned int i; 49 50 for (i = 0; i < ETNA_MAX_PIPES; i++) { 51 struct etnaviv_gpu *g = priv->gpu[i]; 52 53 if (g) { 54 int ret; 55 56 ret = etnaviv_gpu_init(g); 57 if (ret) 58 priv->gpu[i] = NULL; 59 } 60 } 61 } 62 63 static int etnaviv_open(struct drm_device *dev, struct drm_file *file) 64 { 65 struct etnaviv_drm_private *priv = dev->dev_private; 66 struct etnaviv_file_private *ctx; 67 int ret, i; 68 69 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 70 if (!ctx) 71 return -ENOMEM; 72 73 ret = xa_alloc_cyclic(&priv->active_contexts, &ctx->id, ctx, 74 xa_limit_32b, &priv->next_context_id, GFP_KERNEL); 75 if (ret < 0) 76 goto out_free; 77 78 ctx->mmu = etnaviv_iommu_context_init(priv->mmu_global, 79 priv->cmdbuf_suballoc); 80 if (!ctx->mmu) { 81 ret = -ENOMEM; 82 goto out_free; 83 } 84 85 for (i = 0; i < ETNA_MAX_PIPES; i++) { 86 struct etnaviv_gpu *gpu = priv->gpu[i]; 87 struct drm_gpu_scheduler *sched; 88 89 if (gpu) { 90 sched = &gpu->sched; 91 drm_sched_entity_init(&ctx->sched_entity[i], 92 DRM_SCHED_PRIORITY_NORMAL, &sched, 93 1, NULL); 94 } 95 } 96 97 file->driver_priv = ctx; 98 99 return 0; 100 101 out_free: 102 kfree(ctx); 103 return ret; 104 } 105 106 static void etnaviv_postclose(struct drm_device *dev, struct drm_file *file) 107 { 108 struct etnaviv_drm_private *priv = dev->dev_private; 109 struct etnaviv_file_private *ctx = file->driver_priv; 110 unsigned int i; 111 112 for (i = 0; i < ETNA_MAX_PIPES; i++) { 113 struct etnaviv_gpu *gpu = priv->gpu[i]; 114 115 if (gpu) 116 drm_sched_entity_destroy(&ctx->sched_entity[i]); 117 } 118 119 etnaviv_iommu_context_put(ctx->mmu); 120 121 xa_erase(&priv->active_contexts, ctx->id); 122 123 kfree(ctx); 124 } 125 126 /* 127 * DRM debugfs: 128 */ 129 130 #ifdef CONFIG_DEBUG_FS 131 static int etnaviv_gem_show(struct drm_device *dev, struct seq_file *m) 132 { 133 struct etnaviv_drm_private *priv = dev->dev_private; 134 135 etnaviv_gem_describe_objects(priv, m); 136 137 return 0; 138 } 139 140 static int etnaviv_mm_show(struct drm_device *dev, struct seq_file *m) 141 { 142 struct drm_printer p = drm_seq_file_printer(m); 143 144 read_lock(&dev->vma_offset_manager->vm_lock); 145 drm_mm_print(&dev->vma_offset_manager->vm_addr_space_mm, &p); 146 read_unlock(&dev->vma_offset_manager->vm_lock); 147 148 return 0; 149 } 150 151 static int etnaviv_mmu_show(struct etnaviv_gpu *gpu, struct seq_file *m) 152 { 153 struct drm_printer p = drm_seq_file_printer(m); 154 struct etnaviv_iommu_context *mmu_context; 155 156 seq_printf(m, "Active Objects (%s):\n", dev_name(gpu->dev)); 157 158 /* 159 * Lock the GPU to avoid a MMU context switch just now and elevate 160 * the refcount of the current context to avoid it disappearing from 161 * under our feet. 162 */ 163 mutex_lock(&gpu->lock); 164 mmu_context = gpu->mmu_context; 165 if (mmu_context) 166 etnaviv_iommu_context_get(mmu_context); 167 mutex_unlock(&gpu->lock); 168 169 if (!mmu_context) 170 return 0; 171 172 mutex_lock(&mmu_context->lock); 173 drm_mm_print(&mmu_context->mm, &p); 174 mutex_unlock(&mmu_context->lock); 175 176 etnaviv_iommu_context_put(mmu_context); 177 178 return 0; 179 } 180 181 static void etnaviv_buffer_dump(struct etnaviv_gpu *gpu, struct seq_file *m) 182 { 183 struct etnaviv_cmdbuf *buf = &gpu->buffer; 184 u32 size = buf->size; 185 u32 *ptr = buf->vaddr; 186 u32 i; 187 188 seq_printf(m, "virt %p - phys 0x%llx - free 0x%08x\n", 189 buf->vaddr, (u64)etnaviv_cmdbuf_get_pa(buf), 190 size - buf->user_size); 191 192 for (i = 0; i < size / 4; i++) { 193 if (i && !(i % 4)) 194 seq_puts(m, "\n"); 195 if (i % 4 == 0) 196 seq_printf(m, "\t0x%p: ", ptr + i); 197 seq_printf(m, "%08x ", *(ptr + i)); 198 } 199 seq_puts(m, "\n"); 200 } 201 202 static int etnaviv_ring_show(struct etnaviv_gpu *gpu, struct seq_file *m) 203 { 204 seq_printf(m, "Ring Buffer (%s): ", dev_name(gpu->dev)); 205 206 mutex_lock(&gpu->lock); 207 etnaviv_buffer_dump(gpu, m); 208 mutex_unlock(&gpu->lock); 209 210 return 0; 211 } 212 213 static int show_unlocked(struct seq_file *m, void *arg) 214 { 215 struct drm_info_node *node = (struct drm_info_node *) m->private; 216 struct drm_device *dev = node->minor->dev; 217 int (*show)(struct drm_device *dev, struct seq_file *m) = 218 node->info_ent->data; 219 220 return show(dev, m); 221 } 222 223 static int show_each_gpu(struct seq_file *m, void *arg) 224 { 225 struct drm_info_node *node = (struct drm_info_node *) m->private; 226 struct drm_device *dev = node->minor->dev; 227 struct etnaviv_drm_private *priv = dev->dev_private; 228 struct etnaviv_gpu *gpu; 229 int (*show)(struct etnaviv_gpu *gpu, struct seq_file *m) = 230 node->info_ent->data; 231 unsigned int i; 232 int ret = 0; 233 234 for (i = 0; i < ETNA_MAX_PIPES; i++) { 235 gpu = priv->gpu[i]; 236 if (!gpu) 237 continue; 238 239 ret = show(gpu, m); 240 if (ret < 0) 241 break; 242 } 243 244 return ret; 245 } 246 247 static struct drm_info_list etnaviv_debugfs_list[] = { 248 {"gpu", show_each_gpu, 0, etnaviv_gpu_debugfs}, 249 {"gem", show_unlocked, 0, etnaviv_gem_show}, 250 { "mm", show_unlocked, 0, etnaviv_mm_show }, 251 {"mmu", show_each_gpu, 0, etnaviv_mmu_show}, 252 {"ring", show_each_gpu, 0, etnaviv_ring_show}, 253 }; 254 255 static void etnaviv_debugfs_init(struct drm_minor *minor) 256 { 257 drm_debugfs_create_files(etnaviv_debugfs_list, 258 ARRAY_SIZE(etnaviv_debugfs_list), 259 minor->debugfs_root, minor); 260 } 261 #endif 262 263 /* 264 * DRM ioctls: 265 */ 266 267 static int etnaviv_ioctl_get_param(struct drm_device *dev, void *data, 268 struct drm_file *file) 269 { 270 struct etnaviv_drm_private *priv = dev->dev_private; 271 struct drm_etnaviv_param *args = data; 272 struct etnaviv_gpu *gpu; 273 274 if (args->pipe >= ETNA_MAX_PIPES) 275 return -EINVAL; 276 277 gpu = priv->gpu[args->pipe]; 278 if (!gpu) 279 return -ENXIO; 280 281 return etnaviv_gpu_get_param(gpu, args->param, &args->value); 282 } 283 284 static int etnaviv_ioctl_gem_new(struct drm_device *dev, void *data, 285 struct drm_file *file) 286 { 287 struct drm_etnaviv_gem_new *args = data; 288 289 if (args->flags & ~(ETNA_BO_CACHED | ETNA_BO_WC | ETNA_BO_UNCACHED | 290 ETNA_BO_FORCE_MMU)) 291 return -EINVAL; 292 293 return etnaviv_gem_new_handle(dev, file, args->size, 294 args->flags, &args->handle); 295 } 296 297 static int etnaviv_ioctl_gem_cpu_prep(struct drm_device *dev, void *data, 298 struct drm_file *file) 299 { 300 struct drm_etnaviv_gem_cpu_prep *args = data; 301 struct drm_gem_object *obj; 302 int ret; 303 304 if (args->op & ~(ETNA_PREP_READ | ETNA_PREP_WRITE | ETNA_PREP_NOSYNC)) 305 return -EINVAL; 306 307 obj = drm_gem_object_lookup(file, args->handle); 308 if (!obj) 309 return -ENOENT; 310 311 ret = etnaviv_gem_cpu_prep(obj, args->op, &args->timeout); 312 313 drm_gem_object_put(obj); 314 315 return ret; 316 } 317 318 static int etnaviv_ioctl_gem_cpu_fini(struct drm_device *dev, void *data, 319 struct drm_file *file) 320 { 321 struct drm_etnaviv_gem_cpu_fini *args = data; 322 struct drm_gem_object *obj; 323 int ret; 324 325 if (args->flags) 326 return -EINVAL; 327 328 obj = drm_gem_object_lookup(file, args->handle); 329 if (!obj) 330 return -ENOENT; 331 332 ret = etnaviv_gem_cpu_fini(obj); 333 334 drm_gem_object_put(obj); 335 336 return ret; 337 } 338 339 static int etnaviv_ioctl_gem_info(struct drm_device *dev, void *data, 340 struct drm_file *file) 341 { 342 struct drm_etnaviv_gem_info *args = data; 343 struct drm_gem_object *obj; 344 int ret; 345 346 if (args->pad) 347 return -EINVAL; 348 349 obj = drm_gem_object_lookup(file, args->handle); 350 if (!obj) 351 return -ENOENT; 352 353 ret = etnaviv_gem_mmap_offset(obj, &args->offset); 354 drm_gem_object_put(obj); 355 356 return ret; 357 } 358 359 static int etnaviv_ioctl_wait_fence(struct drm_device *dev, void *data, 360 struct drm_file *file) 361 { 362 struct drm_etnaviv_wait_fence *args = data; 363 struct etnaviv_drm_private *priv = dev->dev_private; 364 struct drm_etnaviv_timespec *timeout = &args->timeout; 365 struct etnaviv_gpu *gpu; 366 367 if (args->flags & ~(ETNA_WAIT_NONBLOCK)) 368 return -EINVAL; 369 370 if (args->pipe >= ETNA_MAX_PIPES) 371 return -EINVAL; 372 373 gpu = priv->gpu[args->pipe]; 374 if (!gpu) 375 return -ENXIO; 376 377 if (args->flags & ETNA_WAIT_NONBLOCK) 378 timeout = NULL; 379 380 return etnaviv_gpu_wait_fence_interruptible(gpu, args->fence, 381 timeout); 382 } 383 384 static int etnaviv_ioctl_gem_userptr(struct drm_device *dev, void *data, 385 struct drm_file *file) 386 { 387 struct drm_etnaviv_gem_userptr *args = data; 388 389 if (args->flags & ~(ETNA_USERPTR_READ|ETNA_USERPTR_WRITE) || 390 args->flags == 0) 391 return -EINVAL; 392 393 if (offset_in_page(args->user_ptr | args->user_size) || 394 (uintptr_t)args->user_ptr != args->user_ptr || 395 (u32)args->user_size != args->user_size || 396 args->user_ptr & ~PAGE_MASK) 397 return -EINVAL; 398 399 if (!access_ok((void __user *)(unsigned long)args->user_ptr, 400 args->user_size)) 401 return -EFAULT; 402 403 return etnaviv_gem_new_userptr(dev, file, args->user_ptr, 404 args->user_size, args->flags, 405 &args->handle); 406 } 407 408 static int etnaviv_ioctl_gem_wait(struct drm_device *dev, void *data, 409 struct drm_file *file) 410 { 411 struct etnaviv_drm_private *priv = dev->dev_private; 412 struct drm_etnaviv_gem_wait *args = data; 413 struct drm_etnaviv_timespec *timeout = &args->timeout; 414 struct drm_gem_object *obj; 415 struct etnaviv_gpu *gpu; 416 int ret; 417 418 if (args->flags & ~(ETNA_WAIT_NONBLOCK)) 419 return -EINVAL; 420 421 if (args->pipe >= ETNA_MAX_PIPES) 422 return -EINVAL; 423 424 gpu = priv->gpu[args->pipe]; 425 if (!gpu) 426 return -ENXIO; 427 428 obj = drm_gem_object_lookup(file, args->handle); 429 if (!obj) 430 return -ENOENT; 431 432 if (args->flags & ETNA_WAIT_NONBLOCK) 433 timeout = NULL; 434 435 ret = etnaviv_gem_wait_bo(gpu, obj, timeout); 436 437 drm_gem_object_put(obj); 438 439 return ret; 440 } 441 442 static int etnaviv_ioctl_pm_query_dom(struct drm_device *dev, void *data, 443 struct drm_file *file) 444 { 445 struct etnaviv_drm_private *priv = dev->dev_private; 446 struct drm_etnaviv_pm_domain *args = data; 447 struct etnaviv_gpu *gpu; 448 449 if (args->pipe >= ETNA_MAX_PIPES) 450 return -EINVAL; 451 452 gpu = priv->gpu[args->pipe]; 453 if (!gpu) 454 return -ENXIO; 455 456 return etnaviv_pm_query_dom(gpu, args); 457 } 458 459 static int etnaviv_ioctl_pm_query_sig(struct drm_device *dev, void *data, 460 struct drm_file *file) 461 { 462 struct etnaviv_drm_private *priv = dev->dev_private; 463 struct drm_etnaviv_pm_signal *args = data; 464 struct etnaviv_gpu *gpu; 465 466 if (args->pipe >= ETNA_MAX_PIPES) 467 return -EINVAL; 468 469 gpu = priv->gpu[args->pipe]; 470 if (!gpu) 471 return -ENXIO; 472 473 return etnaviv_pm_query_sig(gpu, args); 474 } 475 476 static const struct drm_ioctl_desc etnaviv_ioctls[] = { 477 #define ETNA_IOCTL(n, func, flags) \ 478 DRM_IOCTL_DEF_DRV(ETNAVIV_##n, etnaviv_ioctl_##func, flags) 479 ETNA_IOCTL(GET_PARAM, get_param, DRM_RENDER_ALLOW), 480 ETNA_IOCTL(GEM_NEW, gem_new, DRM_RENDER_ALLOW), 481 ETNA_IOCTL(GEM_INFO, gem_info, DRM_RENDER_ALLOW), 482 ETNA_IOCTL(GEM_CPU_PREP, gem_cpu_prep, DRM_RENDER_ALLOW), 483 ETNA_IOCTL(GEM_CPU_FINI, gem_cpu_fini, DRM_RENDER_ALLOW), 484 ETNA_IOCTL(GEM_SUBMIT, gem_submit, DRM_RENDER_ALLOW), 485 ETNA_IOCTL(WAIT_FENCE, wait_fence, DRM_RENDER_ALLOW), 486 ETNA_IOCTL(GEM_USERPTR, gem_userptr, DRM_RENDER_ALLOW), 487 ETNA_IOCTL(GEM_WAIT, gem_wait, DRM_RENDER_ALLOW), 488 ETNA_IOCTL(PM_QUERY_DOM, pm_query_dom, DRM_RENDER_ALLOW), 489 ETNA_IOCTL(PM_QUERY_SIG, pm_query_sig, DRM_RENDER_ALLOW), 490 }; 491 492 static void etnaviv_show_fdinfo(struct drm_printer *p, struct drm_file *file) 493 { 494 drm_show_memory_stats(p, file); 495 } 496 497 static const struct file_operations fops = { 498 .owner = THIS_MODULE, 499 DRM_GEM_FOPS, 500 .show_fdinfo = drm_show_fdinfo, 501 }; 502 503 static const struct drm_driver etnaviv_drm_driver = { 504 .driver_features = DRIVER_GEM | DRIVER_RENDER, 505 .open = etnaviv_open, 506 .postclose = etnaviv_postclose, 507 .gem_prime_import_sg_table = etnaviv_gem_prime_import_sg_table, 508 #ifdef CONFIG_DEBUG_FS 509 .debugfs_init = etnaviv_debugfs_init, 510 #endif 511 .show_fdinfo = etnaviv_show_fdinfo, 512 .ioctls = etnaviv_ioctls, 513 .num_ioctls = DRM_ETNAVIV_NUM_IOCTLS, 514 .fops = &fops, 515 .name = "etnaviv", 516 .desc = "etnaviv DRM", 517 .major = 1, 518 .minor = 4, 519 }; 520 521 /* 522 * Platform driver: 523 */ 524 static int etnaviv_bind(struct device *dev) 525 { 526 struct etnaviv_drm_private *priv; 527 struct drm_device *drm; 528 int ret; 529 530 drm = drm_dev_alloc(&etnaviv_drm_driver, dev); 531 if (IS_ERR(drm)) 532 return PTR_ERR(drm); 533 534 priv = kzalloc(sizeof(*priv), GFP_KERNEL); 535 if (!priv) { 536 dev_err(dev, "failed to allocate private data\n"); 537 ret = -ENOMEM; 538 goto out_put; 539 } 540 drm->dev_private = priv; 541 542 dma_set_max_seg_size(dev, SZ_2G); 543 544 xa_init_flags(&priv->active_contexts, XA_FLAGS_ALLOC); 545 546 mutex_init(&priv->gem_lock); 547 INIT_LIST_HEAD(&priv->gem_list); 548 priv->num_gpus = 0; 549 priv->shm_gfp_mask = GFP_HIGHUSER | __GFP_RETRY_MAYFAIL | __GFP_NOWARN; 550 551 /* 552 * If the GPU is part of a system with DMA addressing limitations, 553 * request pages for our SHM backend buffers from the DMA32 zone to 554 * hopefully avoid performance killing SWIOTLB bounce buffering. 555 */ 556 if (dma_addressing_limited(dev)) { 557 priv->shm_gfp_mask |= GFP_DMA32; 558 priv->shm_gfp_mask &= ~__GFP_HIGHMEM; 559 } 560 561 priv->cmdbuf_suballoc = etnaviv_cmdbuf_suballoc_new(drm->dev); 562 if (IS_ERR(priv->cmdbuf_suballoc)) { 563 dev_err(drm->dev, "Failed to create cmdbuf suballocator\n"); 564 ret = PTR_ERR(priv->cmdbuf_suballoc); 565 goto out_free_priv; 566 } 567 568 dev_set_drvdata(dev, drm); 569 570 ret = component_bind_all(dev, drm); 571 if (ret < 0) 572 goto out_destroy_suballoc; 573 574 load_gpu(drm); 575 576 ret = drm_dev_register(drm, 0); 577 if (ret) 578 goto out_unbind; 579 580 return 0; 581 582 out_unbind: 583 component_unbind_all(dev, drm); 584 out_destroy_suballoc: 585 etnaviv_cmdbuf_suballoc_destroy(priv->cmdbuf_suballoc); 586 out_free_priv: 587 mutex_destroy(&priv->gem_lock); 588 kfree(priv); 589 out_put: 590 drm_dev_put(drm); 591 592 return ret; 593 } 594 595 static void etnaviv_unbind(struct device *dev) 596 { 597 struct drm_device *drm = dev_get_drvdata(dev); 598 struct etnaviv_drm_private *priv = drm->dev_private; 599 600 drm_dev_unregister(drm); 601 602 component_unbind_all(dev, drm); 603 604 etnaviv_cmdbuf_free(priv->flop_reset_data_ppu); 605 kfree(priv->flop_reset_data_ppu); 606 607 etnaviv_cmdbuf_suballoc_destroy(priv->cmdbuf_suballoc); 608 609 xa_destroy(&priv->active_contexts); 610 611 drm->dev_private = NULL; 612 kfree(priv); 613 614 drm_dev_put(drm); 615 } 616 617 static const struct component_master_ops etnaviv_master_ops = { 618 .bind = etnaviv_bind, 619 .unbind = etnaviv_unbind, 620 }; 621 622 static int etnaviv_pdev_probe(struct platform_device *pdev) 623 { 624 struct device *dev = &pdev->dev; 625 struct device_node *first_node = NULL; 626 struct component_match *match = NULL; 627 628 if (!dev->platform_data) { 629 struct device_node *core_node; 630 631 for_each_compatible_node(core_node, NULL, "vivante,gc") { 632 if (!of_device_is_available(core_node)) 633 continue; 634 635 drm_of_component_match_add(dev, &match, 636 component_compare_of, core_node); 637 } 638 } else { 639 char **names = dev->platform_data; 640 unsigned i; 641 642 for (i = 0; names[i]; i++) 643 component_match_add(dev, &match, component_compare_dev_name, names[i]); 644 } 645 646 /* 647 * PTA and MTLB can have 40 bit base addresses, but 648 * unfortunately, an entry in the MTLB can only point to a 649 * 32 bit base address of a STLB. Moreover, to initialize the 650 * MMU we need a command buffer with a 32 bit address because 651 * without an MMU there is only an indentity mapping between 652 * the internal 32 bit addresses and the bus addresses. 653 * 654 * To make things easy, we set the dma_coherent_mask to 32 655 * bit to make sure we are allocating the command buffers and 656 * TLBs in the lower 4 GiB address space. 657 */ 658 if (dma_set_mask(dev, DMA_BIT_MASK(40)) || 659 dma_set_coherent_mask(dev, DMA_BIT_MASK(32))) { 660 dev_dbg(dev, "No suitable DMA available\n"); 661 return -ENODEV; 662 } 663 664 /* 665 * Apply the same DMA configuration to the virtual etnaviv 666 * device as the GPU we found. This assumes that all Vivante 667 * GPUs in the system share the same DMA constraints. 668 */ 669 first_node = etnaviv_of_first_available_node(); 670 if (first_node) { 671 of_dma_configure(dev, first_node, true); 672 of_node_put(first_node); 673 } 674 675 return component_master_add_with_match(dev, &etnaviv_master_ops, match); 676 } 677 678 static void etnaviv_pdev_remove(struct platform_device *pdev) 679 { 680 component_master_del(&pdev->dev, &etnaviv_master_ops); 681 } 682 683 static struct platform_driver etnaviv_platform_driver = { 684 .probe = etnaviv_pdev_probe, 685 .remove = etnaviv_pdev_remove, 686 .driver = { 687 .name = "etnaviv", 688 }, 689 }; 690 691 static int etnaviv_create_platform_device(const char *name, 692 struct platform_device **ppdev) 693 { 694 struct platform_device *pdev; 695 int ret; 696 697 pdev = platform_device_alloc(name, PLATFORM_DEVID_NONE); 698 if (!pdev) 699 return -ENOMEM; 700 701 ret = platform_device_add(pdev); 702 if (ret) { 703 platform_device_put(pdev); 704 return ret; 705 } 706 707 *ppdev = pdev; 708 709 return 0; 710 } 711 712 static void etnaviv_destroy_platform_device(struct platform_device **ppdev) 713 { 714 struct platform_device *pdev = *ppdev; 715 716 if (!pdev) 717 return; 718 719 platform_device_unregister(pdev); 720 721 *ppdev = NULL; 722 } 723 724 static struct platform_device *etnaviv_drm; 725 726 static int __init etnaviv_init(void) 727 { 728 int ret; 729 struct device_node *np; 730 731 etnaviv_validate_init(); 732 733 ret = platform_driver_register(&etnaviv_gpu_driver); 734 if (ret != 0) 735 return ret; 736 737 ret = platform_driver_register(&etnaviv_platform_driver); 738 if (ret != 0) 739 goto unregister_gpu_driver; 740 741 /* 742 * If the DT contains at least one available GPU device, instantiate 743 * the DRM platform device. 744 */ 745 np = etnaviv_of_first_available_node(); 746 if (np) { 747 of_node_put(np); 748 749 ret = etnaviv_create_platform_device("etnaviv", &etnaviv_drm); 750 if (ret) 751 goto unregister_platform_driver; 752 } 753 754 return 0; 755 756 unregister_platform_driver: 757 platform_driver_unregister(&etnaviv_platform_driver); 758 unregister_gpu_driver: 759 platform_driver_unregister(&etnaviv_gpu_driver); 760 return ret; 761 } 762 module_init(etnaviv_init); 763 764 static void __exit etnaviv_exit(void) 765 { 766 etnaviv_destroy_platform_device(&etnaviv_drm); 767 platform_driver_unregister(&etnaviv_platform_driver); 768 platform_driver_unregister(&etnaviv_gpu_driver); 769 } 770 module_exit(etnaviv_exit); 771 772 MODULE_AUTHOR("Christian Gmeiner <christian.gmeiner@gmail.com>"); 773 MODULE_AUTHOR("Russell King <rmk+kernel@armlinux.org.uk>"); 774 MODULE_AUTHOR("Lucas Stach <l.stach@pengutronix.de>"); 775 MODULE_DESCRIPTION("etnaviv DRM Driver"); 776 MODULE_LICENSE("GPL v2"); 777 MODULE_ALIAS("platform:etnaviv"); 778