aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/ttm/ttm_bo.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/ttm/ttm_bo.c')
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo.c130
1 files changed, 57 insertions, 73 deletions
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index a835b6fe42a1..fae5c158351c 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -1002,9 +1002,9 @@ static int ttm_bo_mem_compat(struct ttm_placement *placement,
1002 return -1; 1002 return -1;
1003} 1003}
1004 1004
1005int ttm_buffer_object_validate(struct ttm_buffer_object *bo, 1005int ttm_bo_validate(struct ttm_buffer_object *bo,
1006 struct ttm_placement *placement, 1006 struct ttm_placement *placement,
1007 bool interruptible, bool no_wait) 1007 bool interruptible, bool no_wait)
1008{ 1008{
1009 int ret; 1009 int ret;
1010 1010
@@ -1040,55 +1040,57 @@ int ttm_buffer_object_validate(struct ttm_buffer_object *bo,
1040 } 1040 }
1041 return 0; 1041 return 0;
1042} 1042}
1043EXPORT_SYMBOL(ttm_buffer_object_validate); 1043EXPORT_SYMBOL(ttm_bo_validate);
1044 1044
1045int 1045int ttm_bo_check_placement(struct ttm_buffer_object *bo,
1046ttm_bo_check_placement(struct ttm_buffer_object *bo, 1046 struct ttm_placement *placement)
1047 uint32_t set_flags, uint32_t clr_flags)
1048{ 1047{
1049 uint32_t new_mask = set_flags | clr_flags; 1048 int i;
1050
1051 if ((bo->type == ttm_bo_type_user) &&
1052 (clr_flags & TTM_PL_FLAG_CACHED)) {
1053 printk(KERN_ERR TTM_PFX
1054 "User buffers require cache-coherent memory.\n");
1055 return -EINVAL;
1056 }
1057 1049
1058 if (!capable(CAP_SYS_ADMIN)) { 1050 if (placement->fpfn || placement->lpfn) {
1059 if (new_mask & TTM_PL_FLAG_NO_EVICT) { 1051 if (bo->mem.num_pages > (placement->lpfn - placement->fpfn)) {
1060 printk(KERN_ERR TTM_PFX "Need to be root to modify" 1052 printk(KERN_ERR TTM_PFX "Page number range to small "
1061 " NO_EVICT status.\n"); 1053 "Need %lu pages, range is [%u, %u]\n",
1054 bo->mem.num_pages, placement->fpfn,
1055 placement->lpfn);
1062 return -EINVAL; 1056 return -EINVAL;
1063 } 1057 }
1064 1058 }
1065 if ((clr_flags & bo->mem.placement & TTM_PL_MASK_MEMTYPE) && 1059 for (i = 0; i < placement->num_placement; i++) {
1066 (bo->mem.placement & TTM_PL_FLAG_NO_EVICT)) { 1060 if (!capable(CAP_SYS_ADMIN)) {
1067 printk(KERN_ERR TTM_PFX 1061 if (placement->placement[i] & TTM_PL_FLAG_NO_EVICT) {
1068 "Incompatible memory specification" 1062 printk(KERN_ERR TTM_PFX "Need to be root to "
1069 " for NO_EVICT buffer.\n"); 1063 "modify NO_EVICT status.\n");
1070 return -EINVAL; 1064 return -EINVAL;
1065 }
1066 }
1067 }
1068 for (i = 0; i < placement->num_busy_placement; i++) {
1069 if (!capable(CAP_SYS_ADMIN)) {
1070 if (placement->busy_placement[i] & TTM_PL_FLAG_NO_EVICT) {
1071 printk(KERN_ERR TTM_PFX "Need to be root to "
1072 "modify NO_EVICT status.\n");
1073 return -EINVAL;
1074 }
1071 } 1075 }
1072 } 1076 }
1073 return 0; 1077 return 0;
1074} 1078}
1075 1079
1076int ttm_buffer_object_init(struct ttm_bo_device *bdev, 1080int ttm_bo_init(struct ttm_bo_device *bdev,
1077 struct ttm_buffer_object *bo, 1081 struct ttm_buffer_object *bo,
1078 unsigned long size, 1082 unsigned long size,
1079 enum ttm_bo_type type, 1083 enum ttm_bo_type type,
1080 uint32_t flags, 1084 struct ttm_placement *placement,
1081 uint32_t page_alignment, 1085 uint32_t page_alignment,
1082 unsigned long buffer_start, 1086 unsigned long buffer_start,
1083 bool interruptible, 1087 bool interruptible,
1084 struct file *persistant_swap_storage, 1088 struct file *persistant_swap_storage,
1085 size_t acc_size, 1089 size_t acc_size,
1086 void (*destroy) (struct ttm_buffer_object *)) 1090 void (*destroy) (struct ttm_buffer_object *))
1087{ 1091{
1088 int i, c, ret = 0; 1092 int ret = 0;
1089 unsigned long num_pages; 1093 unsigned long num_pages;
1090 uint32_t placements[8];
1091 struct ttm_placement placement;
1092 1094
1093 size += buffer_start & ~PAGE_MASK; 1095 size += buffer_start & ~PAGE_MASK;
1094 num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; 1096 num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
@@ -1123,38 +1125,21 @@ int ttm_buffer_object_init(struct ttm_bo_device *bdev,
1123 bo->acc_size = acc_size; 1125 bo->acc_size = acc_size;
1124 atomic_inc(&bo->glob->bo_count); 1126 atomic_inc(&bo->glob->bo_count);
1125 1127
1126 ret = ttm_bo_check_placement(bo, flags, 0ULL); 1128 ret = ttm_bo_check_placement(bo, placement);
1127 if (unlikely(ret != 0)) 1129 if (unlikely(ret != 0))
1128 goto out_err; 1130 goto out_err;
1129 1131
1130 /* 1132 /*
1131 * If no caching attributes are set, accept any form of caching.
1132 */
1133
1134 if ((flags & TTM_PL_MASK_CACHING) == 0)
1135 flags |= TTM_PL_MASK_CACHING;
1136
1137 /*
1138 * For ttm_bo_type_device buffers, allocate 1133 * For ttm_bo_type_device buffers, allocate
1139 * address space from the device. 1134 * address space from the device.
1140 */ 1135 */
1141
1142 if (bo->type == ttm_bo_type_device) { 1136 if (bo->type == ttm_bo_type_device) {
1143 ret = ttm_bo_setup_vm(bo); 1137 ret = ttm_bo_setup_vm(bo);
1144 if (ret) 1138 if (ret)
1145 goto out_err; 1139 goto out_err;
1146 } 1140 }
1147 1141
1148 placement.fpfn = 0; 1142 ret = ttm_bo_validate(bo, placement, interruptible, false);
1149 placement.lpfn = 0;
1150 for (i = 0, c = 0; i <= TTM_PL_PRIV5; i++)
1151 if (flags & (1 << i))
1152 placements[c++] = (flags & ~TTM_PL_MASK_MEM) | (1 << i);
1153 placement.placement = placements;
1154 placement.num_placement = c;
1155 placement.busy_placement = placements;
1156 placement.num_busy_placement = c;
1157 ret = ttm_buffer_object_validate(bo, &placement, interruptible, false);
1158 if (ret) 1143 if (ret)
1159 goto out_err; 1144 goto out_err;
1160 1145
@@ -1167,7 +1152,7 @@ out_err:
1167 1152
1168 return ret; 1153 return ret;
1169} 1154}
1170EXPORT_SYMBOL(ttm_buffer_object_init); 1155EXPORT_SYMBOL(ttm_bo_init);
1171 1156
1172static inline size_t ttm_bo_size(struct ttm_bo_global *glob, 1157static inline size_t ttm_bo_size(struct ttm_bo_global *glob,
1173 unsigned long num_pages) 1158 unsigned long num_pages)
@@ -1178,15 +1163,15 @@ static inline size_t ttm_bo_size(struct ttm_bo_global *glob,
1178 return glob->ttm_bo_size + 2 * page_array_size; 1163 return glob->ttm_bo_size + 2 * page_array_size;
1179} 1164}
1180 1165
1181int ttm_buffer_object_create(struct ttm_bo_device *bdev, 1166int ttm_bo_create(struct ttm_bo_device *bdev,
1182 unsigned long size, 1167 unsigned long size,
1183 enum ttm_bo_type type, 1168 enum ttm_bo_type type,
1184 uint32_t flags, 1169 struct ttm_placement *placement,
1185 uint32_t page_alignment, 1170 uint32_t page_alignment,
1186 unsigned long buffer_start, 1171 unsigned long buffer_start,
1187 bool interruptible, 1172 bool interruptible,
1188 struct file *persistant_swap_storage, 1173 struct file *persistant_swap_storage,
1189 struct ttm_buffer_object **p_bo) 1174 struct ttm_buffer_object **p_bo)
1190{ 1175{
1191 struct ttm_buffer_object *bo; 1176 struct ttm_buffer_object *bo;
1192 struct ttm_mem_global *mem_glob = bdev->glob->mem_glob; 1177 struct ttm_mem_global *mem_glob = bdev->glob->mem_glob;
@@ -1205,10 +1190,9 @@ int ttm_buffer_object_create(struct ttm_bo_device *bdev,
1205 return -ENOMEM; 1190 return -ENOMEM;
1206 } 1191 }
1207 1192
1208 ret = ttm_buffer_object_init(bdev, bo, size, type, flags, 1193 ret = ttm_bo_init(bdev, bo, size, type, placement, page_alignment,
1209 page_alignment, buffer_start, 1194 buffer_start, interruptible,
1210 interruptible, 1195 persistant_swap_storage, acc_size, NULL);
1211 persistant_swap_storage, acc_size, NULL);
1212 if (likely(ret == 0)) 1196 if (likely(ret == 0))
1213 *p_bo = bo; 1197 *p_bo = bo;
1214 1198