diff options
-rw-r--r-- | drivers/gpu/drm/ttm/ttm_bo.c | 130 | ||||
-rw-r--r-- | include/drm/ttm/ttm_bo_api.h | 63 |
2 files changed, 87 insertions, 106 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 | ||
1005 | int ttm_buffer_object_validate(struct ttm_buffer_object *bo, | 1005 | int 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 | } |
1043 | EXPORT_SYMBOL(ttm_buffer_object_validate); | 1043 | EXPORT_SYMBOL(ttm_bo_validate); |
1044 | 1044 | ||
1045 | int | 1045 | int ttm_bo_check_placement(struct ttm_buffer_object *bo, |
1046 | ttm_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 | ||
1076 | int ttm_buffer_object_init(struct ttm_bo_device *bdev, | 1080 | int 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 | } |
1170 | EXPORT_SYMBOL(ttm_buffer_object_init); | 1155 | EXPORT_SYMBOL(ttm_bo_init); |
1171 | 1156 | ||
1172 | static inline size_t ttm_bo_size(struct ttm_bo_global *glob, | 1157 | static 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 | ||
1181 | int ttm_buffer_object_create(struct ttm_bo_device *bdev, | 1166 | int 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 | ||
diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h index 4fd498523ce3..81eb9f45883c 100644 --- a/include/drm/ttm/ttm_bo_api.h +++ b/include/drm/ttm/ttm_bo_api.h | |||
@@ -308,7 +308,7 @@ ttm_bo_reference(struct ttm_buffer_object *bo) | |||
308 | extern int ttm_bo_wait(struct ttm_buffer_object *bo, bool lazy, | 308 | extern int ttm_bo_wait(struct ttm_buffer_object *bo, bool lazy, |
309 | bool interruptible, bool no_wait); | 309 | bool interruptible, bool no_wait); |
310 | /** | 310 | /** |
311 | * ttm_buffer_object_validate | 311 | * ttm_bo_validate |
312 | * | 312 | * |
313 | * @bo: The buffer object. | 313 | * @bo: The buffer object. |
314 | * @placement: Proposed placement for the buffer object. | 314 | * @placement: Proposed placement for the buffer object. |
@@ -323,9 +323,9 @@ extern int ttm_bo_wait(struct ttm_buffer_object *bo, bool lazy, | |||
323 | * -EBUSY if no_wait is true and buffer busy. | 323 | * -EBUSY if no_wait is true and buffer busy. |
324 | * -ERESTARTSYS if interrupted by a signal. | 324 | * -ERESTARTSYS if interrupted by a signal. |
325 | */ | 325 | */ |
326 | extern int ttm_buffer_object_validate(struct ttm_buffer_object *bo, | 326 | extern int ttm_bo_validate(struct ttm_buffer_object *bo, |
327 | struct ttm_placement *placement, | 327 | struct ttm_placement *placement, |
328 | bool interruptible, bool no_wait); | 328 | bool interruptible, bool no_wait); |
329 | 329 | ||
330 | /** | 330 | /** |
331 | * ttm_bo_unref | 331 | * ttm_bo_unref |
@@ -362,7 +362,7 @@ ttm_bo_synccpu_write_grab(struct ttm_buffer_object *bo, bool no_wait); | |||
362 | extern void ttm_bo_synccpu_write_release(struct ttm_buffer_object *bo); | 362 | extern void ttm_bo_synccpu_write_release(struct ttm_buffer_object *bo); |
363 | 363 | ||
364 | /** | 364 | /** |
365 | * ttm_buffer_object_init | 365 | * ttm_bo_init |
366 | * | 366 | * |
367 | * @bdev: Pointer to a ttm_bo_device struct. | 367 | * @bdev: Pointer to a ttm_bo_device struct. |
368 | * @bo: Pointer to a ttm_buffer_object to be initialized. | 368 | * @bo: Pointer to a ttm_buffer_object to be initialized. |
@@ -393,17 +393,17 @@ extern void ttm_bo_synccpu_write_release(struct ttm_buffer_object *bo); | |||
393 | * -ERESTARTSYS: Interrupted by signal while sleeping waiting for resources. | 393 | * -ERESTARTSYS: Interrupted by signal while sleeping waiting for resources. |
394 | */ | 394 | */ |
395 | 395 | ||
396 | extern int ttm_buffer_object_init(struct ttm_bo_device *bdev, | 396 | extern int ttm_bo_init(struct ttm_bo_device *bdev, |
397 | struct ttm_buffer_object *bo, | 397 | struct ttm_buffer_object *bo, |
398 | unsigned long size, | 398 | unsigned long size, |
399 | enum ttm_bo_type type, | 399 | enum ttm_bo_type type, |
400 | uint32_t flags, | 400 | struct ttm_placement *placement, |
401 | uint32_t page_alignment, | 401 | uint32_t page_alignment, |
402 | unsigned long buffer_start, | 402 | unsigned long buffer_start, |
403 | bool interrubtible, | 403 | bool interrubtible, |
404 | struct file *persistant_swap_storage, | 404 | struct file *persistant_swap_storage, |
405 | size_t acc_size, | 405 | size_t acc_size, |
406 | void (*destroy) (struct ttm_buffer_object *)); | 406 | void (*destroy) (struct ttm_buffer_object *)); |
407 | /** | 407 | /** |
408 | * ttm_bo_synccpu_object_init | 408 | * ttm_bo_synccpu_object_init |
409 | * | 409 | * |
@@ -424,40 +424,37 @@ extern int ttm_buffer_object_init(struct ttm_bo_device *bdev, | |||
424 | * GEM user interface. | 424 | * GEM user interface. |
425 | * @p_bo: On successful completion *p_bo points to the created object. | 425 | * @p_bo: On successful completion *p_bo points to the created object. |
426 | * | 426 | * |
427 | * This function allocates a ttm_buffer_object, and then calls | 427 | * This function allocates a ttm_buffer_object, and then calls ttm_bo_init |
428 | * ttm_buffer_object_init on that object. | 428 | * on that object. The destroy function is set to kfree(). |
429 | * The destroy function is set to kfree(). | ||
430 | * Returns | 429 | * Returns |
431 | * -ENOMEM: Out of memory. | 430 | * -ENOMEM: Out of memory. |
432 | * -EINVAL: Invalid placement flags. | 431 | * -EINVAL: Invalid placement flags. |
433 | * -ERESTARTSYS: Interrupted by signal while waiting for resources. | 432 | * -ERESTARTSYS: Interrupted by signal while waiting for resources. |
434 | */ | 433 | */ |
435 | 434 | ||
436 | extern int ttm_buffer_object_create(struct ttm_bo_device *bdev, | 435 | extern int ttm_bo_create(struct ttm_bo_device *bdev, |
437 | unsigned long size, | 436 | unsigned long size, |
438 | enum ttm_bo_type type, | 437 | enum ttm_bo_type type, |
439 | uint32_t flags, | 438 | struct ttm_placement *placement, |
440 | uint32_t page_alignment, | 439 | uint32_t page_alignment, |
441 | unsigned long buffer_start, | 440 | unsigned long buffer_start, |
442 | bool interruptible, | 441 | bool interruptible, |
443 | struct file *persistant_swap_storage, | 442 | struct file *persistant_swap_storage, |
444 | struct ttm_buffer_object **p_bo); | 443 | struct ttm_buffer_object **p_bo); |
445 | 444 | ||
446 | /** | 445 | /** |
447 | * ttm_bo_check_placement | 446 | * ttm_bo_check_placement |
448 | * | 447 | * |
449 | * @bo: the buffer object. | 448 | * @bo: the buffer object. |
450 | * @set_flags: placement flags to set. | 449 | * @placement: placements |
451 | * @clr_flags: placement flags to clear. | ||
452 | * | 450 | * |
453 | * Performs minimal validity checking on an intended change of | 451 | * Performs minimal validity checking on an intended change of |
454 | * placement flags. | 452 | * placement flags. |
455 | * Returns | 453 | * Returns |
456 | * -EINVAL: Intended change is invalid or not allowed. | 454 | * -EINVAL: Intended change is invalid or not allowed. |
457 | */ | 455 | */ |
458 | |||
459 | extern int ttm_bo_check_placement(struct ttm_buffer_object *bo, | 456 | extern int ttm_bo_check_placement(struct ttm_buffer_object *bo, |
460 | uint32_t set_flags, uint32_t clr_flags); | 457 | struct ttm_placement *placement); |
461 | 458 | ||
462 | /** | 459 | /** |
463 | * ttm_bo_init_mm | 460 | * ttm_bo_init_mm |