| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright © 2015 Broadcom |
|---|
| 3 | | - * |
|---|
| 4 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 5 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 6 | | - * published by the Free Software Foundation. |
|---|
| 7 | 4 | */ |
|---|
| 8 | 5 | |
|---|
| 9 | 6 | /** |
|---|
| .. | .. |
|---|
| 40 | 37 | return label >= VC4_BO_TYPE_COUNT; |
|---|
| 41 | 38 | } |
|---|
| 42 | 39 | |
|---|
| 43 | | -static void vc4_bo_stats_dump(struct vc4_dev *vc4) |
|---|
| 40 | +static void vc4_bo_stats_print(struct drm_printer *p, struct vc4_dev *vc4) |
|---|
| 44 | 41 | { |
|---|
| 45 | 42 | int i; |
|---|
| 46 | 43 | |
|---|
| .. | .. |
|---|
| 48 | 45 | if (!vc4->bo_labels[i].num_allocated) |
|---|
| 49 | 46 | continue; |
|---|
| 50 | 47 | |
|---|
| 51 | | - DRM_INFO("%30s: %6dkb BOs (%d)\n", |
|---|
| 52 | | - vc4->bo_labels[i].name, |
|---|
| 53 | | - vc4->bo_labels[i].size_allocated / 1024, |
|---|
| 54 | | - vc4->bo_labels[i].num_allocated); |
|---|
| 55 | | - } |
|---|
| 56 | | - |
|---|
| 57 | | - mutex_lock(&vc4->purgeable.lock); |
|---|
| 58 | | - if (vc4->purgeable.num) |
|---|
| 59 | | - DRM_INFO("%30s: %6zdkb BOs (%d)\n", "userspace BO cache", |
|---|
| 60 | | - vc4->purgeable.size / 1024, vc4->purgeable.num); |
|---|
| 61 | | - |
|---|
| 62 | | - if (vc4->purgeable.purged_num) |
|---|
| 63 | | - DRM_INFO("%30s: %6zdkb BOs (%d)\n", "total purged BO", |
|---|
| 64 | | - vc4->purgeable.purged_size / 1024, |
|---|
| 65 | | - vc4->purgeable.purged_num); |
|---|
| 66 | | - mutex_unlock(&vc4->purgeable.lock); |
|---|
| 67 | | -} |
|---|
| 68 | | - |
|---|
| 69 | | -#ifdef CONFIG_DEBUG_FS |
|---|
| 70 | | -int vc4_bo_stats_debugfs(struct seq_file *m, void *unused) |
|---|
| 71 | | -{ |
|---|
| 72 | | - struct drm_info_node *node = (struct drm_info_node *)m->private; |
|---|
| 73 | | - struct drm_device *dev = node->minor->dev; |
|---|
| 74 | | - struct vc4_dev *vc4 = to_vc4_dev(dev); |
|---|
| 75 | | - int i; |
|---|
| 76 | | - |
|---|
| 77 | | - mutex_lock(&vc4->bo_lock); |
|---|
| 78 | | - for (i = 0; i < vc4->num_labels; i++) { |
|---|
| 79 | | - if (!vc4->bo_labels[i].num_allocated) |
|---|
| 80 | | - continue; |
|---|
| 81 | | - |
|---|
| 82 | | - seq_printf(m, "%30s: %6dkb BOs (%d)\n", |
|---|
| 48 | + drm_printf(p, "%30s: %6dkb BOs (%d)\n", |
|---|
| 83 | 49 | vc4->bo_labels[i].name, |
|---|
| 84 | 50 | vc4->bo_labels[i].size_allocated / 1024, |
|---|
| 85 | 51 | vc4->bo_labels[i].num_allocated); |
|---|
| 86 | 52 | } |
|---|
| 87 | | - mutex_unlock(&vc4->bo_lock); |
|---|
| 88 | 53 | |
|---|
| 89 | 54 | mutex_lock(&vc4->purgeable.lock); |
|---|
| 90 | 55 | if (vc4->purgeable.num) |
|---|
| 91 | | - seq_printf(m, "%30s: %6zdkb BOs (%d)\n", "userspace BO cache", |
|---|
| 56 | + drm_printf(p, "%30s: %6zdkb BOs (%d)\n", "userspace BO cache", |
|---|
| 92 | 57 | vc4->purgeable.size / 1024, vc4->purgeable.num); |
|---|
| 93 | 58 | |
|---|
| 94 | 59 | if (vc4->purgeable.purged_num) |
|---|
| 95 | | - seq_printf(m, "%30s: %6zdkb BOs (%d)\n", "total purged BO", |
|---|
| 60 | + drm_printf(p, "%30s: %6zdkb BOs (%d)\n", "total purged BO", |
|---|
| 96 | 61 | vc4->purgeable.purged_size / 1024, |
|---|
| 97 | 62 | vc4->purgeable.purged_num); |
|---|
| 98 | 63 | mutex_unlock(&vc4->purgeable.lock); |
|---|
| 64 | +} |
|---|
| 65 | + |
|---|
| 66 | +static int vc4_bo_stats_debugfs(struct seq_file *m, void *unused) |
|---|
| 67 | +{ |
|---|
| 68 | + struct drm_info_node *node = (struct drm_info_node *)m->private; |
|---|
| 69 | + struct drm_device *dev = node->minor->dev; |
|---|
| 70 | + struct vc4_dev *vc4 = to_vc4_dev(dev); |
|---|
| 71 | + struct drm_printer p = drm_seq_file_printer(m); |
|---|
| 72 | + |
|---|
| 73 | + vc4_bo_stats_print(&p, vc4); |
|---|
| 99 | 74 | |
|---|
| 100 | 75 | return 0; |
|---|
| 101 | 76 | } |
|---|
| 102 | | -#endif |
|---|
| 103 | 77 | |
|---|
| 104 | 78 | /* Takes ownership of *name and returns the appropriate slot for it in |
|---|
| 105 | 79 | * the bo_labels[] array, extending it as necessary. |
|---|
| .. | .. |
|---|
| 200 | 174 | kfree(bo->validated_shader); |
|---|
| 201 | 175 | bo->validated_shader = NULL; |
|---|
| 202 | 176 | } |
|---|
| 203 | | - |
|---|
| 204 | | - reservation_object_fini(&bo->_resv); |
|---|
| 205 | 177 | |
|---|
| 206 | 178 | drm_gem_cma_free_object(obj); |
|---|
| 207 | 179 | } |
|---|
| .. | .. |
|---|
| 427 | 399 | vc4->bo_labels[VC4_BO_TYPE_KERNEL].num_allocated++; |
|---|
| 428 | 400 | vc4->bo_labels[VC4_BO_TYPE_KERNEL].size_allocated += size; |
|---|
| 429 | 401 | mutex_unlock(&vc4->bo_lock); |
|---|
| 430 | | - bo->resv = &bo->_resv; |
|---|
| 431 | | - reservation_object_init(bo->resv); |
|---|
| 432 | 402 | |
|---|
| 433 | 403 | return &bo->base.base; |
|---|
| 434 | 404 | } |
|---|
| .. | .. |
|---|
| 479 | 449 | } |
|---|
| 480 | 450 | |
|---|
| 481 | 451 | if (IS_ERR(cma_obj)) { |
|---|
| 452 | + struct drm_printer p = drm_info_printer(vc4->base.dev); |
|---|
| 482 | 453 | DRM_ERROR("Failed to allocate from CMA:\n"); |
|---|
| 483 | | - vc4_bo_stats_dump(vc4); |
|---|
| 454 | + vc4_bo_stats_print(&p, vc4); |
|---|
| 484 | 455 | return ERR_PTR(-ENOMEM); |
|---|
| 485 | 456 | } |
|---|
| 486 | 457 | bo = to_vc4_bo(&cma_obj->base); |
|---|
| .. | .. |
|---|
| 519 | 490 | bo->madv = VC4_MADV_WILLNEED; |
|---|
| 520 | 491 | |
|---|
| 521 | 492 | ret = drm_gem_handle_create(file_priv, &bo->base.base, &args->handle); |
|---|
| 522 | | - drm_gem_object_put_unlocked(&bo->base.base); |
|---|
| 493 | + drm_gem_object_put(&bo->base.base); |
|---|
| 523 | 494 | |
|---|
| 524 | 495 | return ret; |
|---|
| 525 | 496 | } |
|---|
| .. | .. |
|---|
| 619 | 590 | { |
|---|
| 620 | 591 | struct vc4_dev *vc4 = |
|---|
| 621 | 592 | container_of(work, struct vc4_dev, bo_cache.time_work); |
|---|
| 622 | | - struct drm_device *dev = vc4->dev; |
|---|
| 593 | + struct drm_device *dev = &vc4->base; |
|---|
| 623 | 594 | |
|---|
| 624 | 595 | mutex_lock(&vc4->bo_lock); |
|---|
| 625 | 596 | vc4_bo_cache_free_old(dev); |
|---|
| .. | .. |
|---|
| 684 | 655 | schedule_work(&vc4->bo_cache.time_work); |
|---|
| 685 | 656 | } |
|---|
| 686 | 657 | |
|---|
| 687 | | -struct reservation_object *vc4_prime_res_obj(struct drm_gem_object *obj) |
|---|
| 688 | | -{ |
|---|
| 689 | | - struct vc4_bo *bo = to_vc4_bo(obj); |
|---|
| 690 | | - |
|---|
| 691 | | - return bo->resv; |
|---|
| 692 | | -} |
|---|
| 693 | | - |
|---|
| 694 | | -struct dma_buf * |
|---|
| 695 | | -vc4_prime_export(struct drm_device *dev, struct drm_gem_object *obj, int flags) |
|---|
| 658 | +struct dma_buf * vc4_prime_export(struct drm_gem_object *obj, int flags) |
|---|
| 696 | 659 | { |
|---|
| 697 | 660 | struct vc4_bo *bo = to_vc4_bo(obj); |
|---|
| 698 | 661 | struct dma_buf *dmabuf; |
|---|
| .. | .. |
|---|
| 714 | 677 | return ERR_PTR(ret); |
|---|
| 715 | 678 | } |
|---|
| 716 | 679 | |
|---|
| 717 | | - dmabuf = drm_gem_prime_export(dev, obj, flags); |
|---|
| 680 | + dmabuf = drm_gem_prime_export(obj, flags); |
|---|
| 718 | 681 | if (IS_ERR(dmabuf)) |
|---|
| 719 | 682 | vc4_bo_dec_usecnt(bo); |
|---|
| 720 | 683 | |
|---|
| .. | .. |
|---|
| 822 | 785 | struct sg_table *sgt) |
|---|
| 823 | 786 | { |
|---|
| 824 | 787 | struct drm_gem_object *obj; |
|---|
| 825 | | - struct vc4_bo *bo; |
|---|
| 826 | 788 | |
|---|
| 827 | 789 | obj = drm_gem_cma_prime_import_sg_table(dev, attach, sgt); |
|---|
| 828 | 790 | if (IS_ERR(obj)) |
|---|
| 829 | 791 | return obj; |
|---|
| 830 | 792 | |
|---|
| 831 | | - bo = to_vc4_bo(obj); |
|---|
| 832 | | - bo->resv = attach->dmabuf->resv; |
|---|
| 833 | | - |
|---|
| 834 | 793 | return obj; |
|---|
| 794 | +} |
|---|
| 795 | + |
|---|
| 796 | +static int vc4_grab_bin_bo(struct vc4_dev *vc4, struct vc4_file *vc4file) |
|---|
| 797 | +{ |
|---|
| 798 | + int ret; |
|---|
| 799 | + |
|---|
| 800 | + if (!vc4->v3d) |
|---|
| 801 | + return -ENODEV; |
|---|
| 802 | + |
|---|
| 803 | + if (vc4file->bin_bo_used) |
|---|
| 804 | + return 0; |
|---|
| 805 | + |
|---|
| 806 | + ret = vc4_v3d_bin_bo_get(vc4, &vc4file->bin_bo_used); |
|---|
| 807 | + if (ret) |
|---|
| 808 | + return ret; |
|---|
| 809 | + |
|---|
| 810 | + return 0; |
|---|
| 835 | 811 | } |
|---|
| 836 | 812 | |
|---|
| 837 | 813 | int vc4_create_bo_ioctl(struct drm_device *dev, void *data, |
|---|
| 838 | 814 | struct drm_file *file_priv) |
|---|
| 839 | 815 | { |
|---|
| 840 | 816 | struct drm_vc4_create_bo *args = data; |
|---|
| 817 | + struct vc4_file *vc4file = file_priv->driver_priv; |
|---|
| 818 | + struct vc4_dev *vc4 = to_vc4_dev(dev); |
|---|
| 841 | 819 | struct vc4_bo *bo = NULL; |
|---|
| 842 | 820 | int ret; |
|---|
| 821 | + |
|---|
| 822 | + ret = vc4_grab_bin_bo(vc4, vc4file); |
|---|
| 823 | + if (ret) |
|---|
| 824 | + return ret; |
|---|
| 843 | 825 | |
|---|
| 844 | 826 | /* |
|---|
| 845 | 827 | * We can't allocate from the BO cache, because the BOs don't |
|---|
| .. | .. |
|---|
| 852 | 834 | bo->madv = VC4_MADV_WILLNEED; |
|---|
| 853 | 835 | |
|---|
| 854 | 836 | ret = drm_gem_handle_create(file_priv, &bo->base.base, &args->handle); |
|---|
| 855 | | - drm_gem_object_put_unlocked(&bo->base.base); |
|---|
| 837 | + drm_gem_object_put(&bo->base.base); |
|---|
| 856 | 838 | |
|---|
| 857 | 839 | return ret; |
|---|
| 858 | 840 | } |
|---|
| .. | .. |
|---|
| 872 | 854 | /* The mmap offset was set up at BO allocation time. */ |
|---|
| 873 | 855 | args->offset = drm_vma_node_offset_addr(&gem_obj->vma_node); |
|---|
| 874 | 856 | |
|---|
| 875 | | - drm_gem_object_put_unlocked(gem_obj); |
|---|
| 857 | + drm_gem_object_put(gem_obj); |
|---|
| 876 | 858 | return 0; |
|---|
| 877 | 859 | } |
|---|
| 878 | 860 | |
|---|
| .. | .. |
|---|
| 881 | 863 | struct drm_file *file_priv) |
|---|
| 882 | 864 | { |
|---|
| 883 | 865 | struct drm_vc4_create_shader_bo *args = data; |
|---|
| 866 | + struct vc4_file *vc4file = file_priv->driver_priv; |
|---|
| 867 | + struct vc4_dev *vc4 = to_vc4_dev(dev); |
|---|
| 884 | 868 | struct vc4_bo *bo = NULL; |
|---|
| 885 | 869 | int ret; |
|---|
| 886 | 870 | |
|---|
| .. | .. |
|---|
| 899 | 883 | DRM_INFO("Pad set: 0x%08x\n", args->pad); |
|---|
| 900 | 884 | return -EINVAL; |
|---|
| 901 | 885 | } |
|---|
| 886 | + |
|---|
| 887 | + ret = vc4_grab_bin_bo(vc4, vc4file); |
|---|
| 888 | + if (ret) |
|---|
| 889 | + return ret; |
|---|
| 902 | 890 | |
|---|
| 903 | 891 | bo = vc4_bo_create(dev, args->size, true, VC4_BO_TYPE_V3D_SHADER); |
|---|
| 904 | 892 | if (IS_ERR(bo)) |
|---|
| .. | .. |
|---|
| 929 | 917 | */ |
|---|
| 930 | 918 | ret = drm_gem_handle_create(file_priv, &bo->base.base, &args->handle); |
|---|
| 931 | 919 | |
|---|
| 932 | | - fail: |
|---|
| 933 | | - drm_gem_object_put_unlocked(&bo->base.base); |
|---|
| 920 | +fail: |
|---|
| 921 | + drm_gem_object_put(&bo->base.base); |
|---|
| 934 | 922 | |
|---|
| 935 | 923 | return ret; |
|---|
| 936 | 924 | } |
|---|
| .. | .. |
|---|
| 977 | 965 | bo = to_vc4_bo(gem_obj); |
|---|
| 978 | 966 | bo->t_format = t_format; |
|---|
| 979 | 967 | |
|---|
| 980 | | - drm_gem_object_put_unlocked(gem_obj); |
|---|
| 968 | + drm_gem_object_put(gem_obj); |
|---|
| 981 | 969 | |
|---|
| 982 | 970 | return 0; |
|---|
| 983 | 971 | } |
|---|
| .. | .. |
|---|
| 1012 | 1000 | else |
|---|
| 1013 | 1001 | args->modifier = DRM_FORMAT_MOD_NONE; |
|---|
| 1014 | 1002 | |
|---|
| 1015 | | - drm_gem_object_put_unlocked(gem_obj); |
|---|
| 1003 | + drm_gem_object_put(gem_obj); |
|---|
| 1016 | 1004 | |
|---|
| 1017 | 1005 | return 0; |
|---|
| 1018 | 1006 | } |
|---|
| 1019 | 1007 | |
|---|
| 1008 | +static void vc4_bo_cache_destroy(struct drm_device *dev, void *unused); |
|---|
| 1020 | 1009 | int vc4_bo_cache_init(struct drm_device *dev) |
|---|
| 1021 | 1010 | { |
|---|
| 1022 | 1011 | struct vc4_dev *vc4 = to_vc4_dev(dev); |
|---|
| .. | .. |
|---|
| 1038 | 1027 | |
|---|
| 1039 | 1028 | mutex_init(&vc4->bo_lock); |
|---|
| 1040 | 1029 | |
|---|
| 1030 | + vc4_debugfs_add_file(dev, "bo_stats", vc4_bo_stats_debugfs, NULL); |
|---|
| 1031 | + |
|---|
| 1041 | 1032 | INIT_LIST_HEAD(&vc4->bo_cache.time_list); |
|---|
| 1042 | 1033 | |
|---|
| 1043 | 1034 | INIT_WORK(&vc4->bo_cache.time_work, vc4_bo_cache_time_work); |
|---|
| 1044 | 1035 | timer_setup(&vc4->bo_cache.time_timer, vc4_bo_cache_time_timer, 0); |
|---|
| 1045 | 1036 | |
|---|
| 1046 | | - return 0; |
|---|
| 1037 | + return drmm_add_action_or_reset(dev, vc4_bo_cache_destroy, NULL); |
|---|
| 1047 | 1038 | } |
|---|
| 1048 | 1039 | |
|---|
| 1049 | | -void vc4_bo_cache_destroy(struct drm_device *dev) |
|---|
| 1040 | +static void vc4_bo_cache_destroy(struct drm_device *dev, void *unused) |
|---|
| 1050 | 1041 | { |
|---|
| 1051 | 1042 | struct vc4_dev *vc4 = to_vc4_dev(dev); |
|---|
| 1052 | 1043 | int i; |
|---|
| .. | .. |
|---|
| 1101 | 1092 | ret = -ENOMEM; |
|---|
| 1102 | 1093 | mutex_unlock(&vc4->bo_lock); |
|---|
| 1103 | 1094 | |
|---|
| 1104 | | - drm_gem_object_put_unlocked(gem_obj); |
|---|
| 1095 | + drm_gem_object_put(gem_obj); |
|---|
| 1105 | 1096 | |
|---|
| 1106 | 1097 | return ret; |
|---|
| 1107 | 1098 | } |
|---|