diff options
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/mm_gk20a.c | 42 |
1 files changed, 29 insertions, 13 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c index 5e1505c4..735c262a 100644 --- a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c | |||
@@ -1054,6 +1054,27 @@ static struct mapped_buffer_node *find_mapped_buffer_range_locked( | |||
1054 | return NULL; | 1054 | return NULL; |
1055 | } | 1055 | } |
1056 | 1056 | ||
1057 | /* find the first mapped buffer with GPU VA less than addr */ | ||
1058 | static struct mapped_buffer_node *find_mapped_buffer_less_than_locked( | ||
1059 | struct rb_root *root, u64 addr) | ||
1060 | { | ||
1061 | struct rb_node *node = root->rb_node; | ||
1062 | struct mapped_buffer_node *ret = NULL; | ||
1063 | |||
1064 | while (node) { | ||
1065 | struct mapped_buffer_node *mapped_buffer = | ||
1066 | container_of(node, struct mapped_buffer_node, node); | ||
1067 | if (mapped_buffer->addr >= addr) | ||
1068 | node = node->rb_left; | ||
1069 | else { | ||
1070 | ret = mapped_buffer; | ||
1071 | node = node->rb_right; | ||
1072 | } | ||
1073 | } | ||
1074 | |||
1075 | return ret; | ||
1076 | } | ||
1077 | |||
1057 | #define BFR_ATTRS (sizeof(nvmap_bfr_param)/sizeof(nvmap_bfr_param[0])) | 1078 | #define BFR_ATTRS (sizeof(nvmap_bfr_param)/sizeof(nvmap_bfr_param[0])) |
1058 | 1079 | ||
1059 | struct buffer_attrs { | 1080 | struct buffer_attrs { |
@@ -1165,19 +1186,14 @@ static int validate_fixed_buffer(struct vm_gk20a *vm, | |||
1165 | return -EINVAL; | 1186 | return -EINVAL; |
1166 | } | 1187 | } |
1167 | 1188 | ||
1168 | /* check that this mappings does not collide with existing | 1189 | /* check that this mapping does not collide with existing |
1169 | * mappings by checking the overlapping area between the current | 1190 | * mappings by checking the buffer with the highest GPU VA |
1170 | * buffer and all other mapped buffers */ | 1191 | * that is less than our buffer end */ |
1171 | 1192 | buffer = find_mapped_buffer_less_than_locked( | |
1172 | list_for_each_entry(buffer, | 1193 | &vm->mapped_buffers, map_offset + map_size); |
1173 | &va_node->va_buffers_list, va_buffers_list) { | 1194 | if (buffer && buffer->addr + buffer->size > map_offset) { |
1174 | s64 begin = max(buffer->addr, map_offset); | 1195 | gk20a_warn(dev, "overlapping buffer map requested"); |
1175 | s64 end = min(buffer->addr + | 1196 | return -EINVAL; |
1176 | buffer->size, map_offset + map_size); | ||
1177 | if (end - begin > 0) { | ||
1178 | gk20a_warn(dev, "overlapping buffer map requested"); | ||
1179 | return -EINVAL; | ||
1180 | } | ||
1181 | } | 1197 | } |
1182 | 1198 | ||
1183 | return 0; | 1199 | return 0; |