diff options
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon.h | 6 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_cs.c | 25 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_drv.c | 5 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_gem.c | 68 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_kms.c | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_object.c | 3 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_prime.c | 10 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_ttm.c | 145 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_vm.c | 3 | ||||
| -rw-r--r-- | include/uapi/drm/radeon_drm.h | 16 |
10 files changed, 279 insertions, 3 deletions
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 9e1732eb402c..6f38a23a5810 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
| @@ -2138,6 +2138,8 @@ int radeon_gem_info_ioctl(struct drm_device *dev, void *data, | |||
| 2138 | struct drm_file *filp); | 2138 | struct drm_file *filp); |
| 2139 | int radeon_gem_create_ioctl(struct drm_device *dev, void *data, | 2139 | int radeon_gem_create_ioctl(struct drm_device *dev, void *data, |
| 2140 | struct drm_file *filp); | 2140 | struct drm_file *filp); |
| 2141 | int radeon_gem_userptr_ioctl(struct drm_device *dev, void *data, | ||
| 2142 | struct drm_file *filp); | ||
| 2141 | int radeon_gem_pin_ioctl(struct drm_device *dev, void *data, | 2143 | int radeon_gem_pin_ioctl(struct drm_device *dev, void *data, |
| 2142 | struct drm_file *file_priv); | 2144 | struct drm_file *file_priv); |
| 2143 | int radeon_gem_unpin_ioctl(struct drm_device *dev, void *data, | 2145 | int radeon_gem_unpin_ioctl(struct drm_device *dev, void *data, |
| @@ -2871,6 +2873,10 @@ extern void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enabl | |||
| 2871 | extern void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable); | 2873 | extern void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable); |
| 2872 | extern void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain); | 2874 | extern void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain); |
| 2873 | extern bool radeon_ttm_bo_is_radeon_bo(struct ttm_buffer_object *bo); | 2875 | extern bool radeon_ttm_bo_is_radeon_bo(struct ttm_buffer_object *bo); |
| 2876 | extern int radeon_ttm_tt_set_userptr(struct ttm_tt *ttm, uint64_t addr, | ||
| 2877 | uint32_t flags); | ||
| 2878 | extern bool radeon_ttm_tt_has_userptr(struct ttm_tt *ttm); | ||
| 2879 | extern bool radeon_ttm_tt_is_readonly(struct ttm_tt *ttm); | ||
| 2874 | extern void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64 base); | 2880 | extern void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64 base); |
| 2875 | extern void radeon_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc); | 2881 | extern void radeon_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc); |
| 2876 | extern int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon); | 2882 | extern int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon); |
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index ee712c199b25..1321491cf499 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c | |||
| @@ -78,7 +78,8 @@ static int radeon_cs_parser_relocs(struct radeon_cs_parser *p) | |||
| 78 | struct radeon_cs_chunk *chunk; | 78 | struct radeon_cs_chunk *chunk; |
| 79 | struct radeon_cs_buckets buckets; | 79 | struct radeon_cs_buckets buckets; |
| 80 | unsigned i, j; | 80 | unsigned i, j; |
| 81 | bool duplicate; | 81 | bool duplicate, need_mmap_lock = false; |
| 82 | int r; | ||
| 82 | 83 | ||
| 83 | if (p->chunk_relocs_idx == -1) { | 84 | if (p->chunk_relocs_idx == -1) { |
| 84 | return 0; | 85 | return 0; |
| @@ -164,6 +165,19 @@ static int radeon_cs_parser_relocs(struct radeon_cs_parser *p) | |||
| 164 | p->relocs[i].allowed_domains = domain; | 165 | p->relocs[i].allowed_domains = domain; |
| 165 | } | 166 | } |
| 166 | 167 | ||
| 168 | if (radeon_ttm_tt_has_userptr(p->relocs[i].robj->tbo.ttm)) { | ||
| 169 | uint32_t domain = p->relocs[i].prefered_domains; | ||
| 170 | if (!(domain & RADEON_GEM_DOMAIN_GTT)) { | ||
| 171 | DRM_ERROR("Only RADEON_GEM_DOMAIN_GTT is " | ||
| 172 | "allowed for userptr BOs\n"); | ||
| 173 | return -EINVAL; | ||
| 174 | } | ||
| 175 | need_mmap_lock = true; | ||
| 176 | domain = RADEON_GEM_DOMAIN_GTT; | ||
| 177 | p->relocs[i].prefered_domains = domain; | ||
| 178 | p->relocs[i].allowed_domains = domain; | ||
| 179 | } | ||
| 180 | |||
| 167 | p->relocs[i].tv.bo = &p->relocs[i].robj->tbo; | 181 | p->relocs[i].tv.bo = &p->relocs[i].robj->tbo; |
| 168 | p->relocs[i].handle = r->handle; | 182 | p->relocs[i].handle = r->handle; |
| 169 | 183 | ||
| @@ -176,8 +190,15 @@ static int radeon_cs_parser_relocs(struct radeon_cs_parser *p) | |||
| 176 | if (p->cs_flags & RADEON_CS_USE_VM) | 190 | if (p->cs_flags & RADEON_CS_USE_VM) |
| 177 | p->vm_bos = radeon_vm_get_bos(p->rdev, p->ib.vm, | 191 | p->vm_bos = radeon_vm_get_bos(p->rdev, p->ib.vm, |
| 178 | &p->validated); | 192 | &p->validated); |
| 193 | if (need_mmap_lock) | ||
| 194 | down_read(¤t->mm->mmap_sem); | ||
| 195 | |||
| 196 | r = radeon_bo_list_validate(p->rdev, &p->ticket, &p->validated, p->ring); | ||
| 179 | 197 | ||
| 180 | return radeon_bo_list_validate(p->rdev, &p->ticket, &p->validated, p->ring); | 198 | if (need_mmap_lock) |
| 199 | up_read(¤t->mm->mmap_sem); | ||
| 200 | |||
| 201 | return r; | ||
| 181 | } | 202 | } |
| 182 | 203 | ||
| 183 | static int radeon_cs_get_ring(struct radeon_cs_parser *p, u32 ring, s32 priority) | 204 | static int radeon_cs_get_ring(struct radeon_cs_parser *p, u32 ring, s32 priority) |
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index a773830c6c40..5b18af926527 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c | |||
| @@ -114,6 +114,9 @@ int radeon_gem_object_open(struct drm_gem_object *obj, | |||
| 114 | struct drm_file *file_priv); | 114 | struct drm_file *file_priv); |
| 115 | void radeon_gem_object_close(struct drm_gem_object *obj, | 115 | void radeon_gem_object_close(struct drm_gem_object *obj, |
| 116 | struct drm_file *file_priv); | 116 | struct drm_file *file_priv); |
| 117 | struct dma_buf *radeon_gem_prime_export(struct drm_device *dev, | ||
| 118 | struct drm_gem_object *gobj, | ||
| 119 | int flags); | ||
| 117 | extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, | 120 | extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, |
| 118 | unsigned int flags, | 121 | unsigned int flags, |
| 119 | int *vpos, int *hpos, ktime_t *stime, | 122 | int *vpos, int *hpos, ktime_t *stime, |
| @@ -568,7 +571,7 @@ static struct drm_driver kms_driver = { | |||
| 568 | 571 | ||
| 569 | .prime_handle_to_fd = drm_gem_prime_handle_to_fd, | 572 | .prime_handle_to_fd = drm_gem_prime_handle_to_fd, |
| 570 | .prime_fd_to_handle = drm_gem_prime_fd_to_handle, | 573 | .prime_fd_to_handle = drm_gem_prime_fd_to_handle, |
| 571 | .gem_prime_export = drm_gem_prime_export, | 574 | .gem_prime_export = radeon_gem_prime_export, |
| 572 | .gem_prime_import = drm_gem_prime_import, | 575 | .gem_prime_import = drm_gem_prime_import, |
| 573 | .gem_prime_pin = radeon_gem_prime_pin, | 576 | .gem_prime_pin = radeon_gem_prime_pin, |
| 574 | .gem_prime_unpin = radeon_gem_prime_unpin, | 577 | .gem_prime_unpin = radeon_gem_prime_unpin, |
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index bfd7e1b0ff3f..993ab223b503 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c | |||
| @@ -272,6 +272,65 @@ int radeon_gem_create_ioctl(struct drm_device *dev, void *data, | |||
| 272 | return 0; | 272 | return 0; |
| 273 | } | 273 | } |
| 274 | 274 | ||
| 275 | int radeon_gem_userptr_ioctl(struct drm_device *dev, void *data, | ||
| 276 | struct drm_file *filp) | ||
| 277 | { | ||
| 278 | struct radeon_device *rdev = dev->dev_private; | ||
| 279 | struct drm_radeon_gem_userptr *args = data; | ||
| 280 | struct drm_gem_object *gobj; | ||
| 281 | struct radeon_bo *bo; | ||
| 282 | uint32_t handle; | ||
| 283 | int r; | ||
| 284 | |||
| 285 | if (offset_in_page(args->addr | args->size)) | ||
| 286 | return -EINVAL; | ||
| 287 | |||
| 288 | /* we only support read only mappings for now */ | ||
| 289 | if (!(args->flags & RADEON_GEM_USERPTR_READONLY)) | ||
| 290 | return -EACCES; | ||
| 291 | |||
| 292 | /* reject unknown flag values */ | ||
| 293 | if (args->flags & ~RADEON_GEM_USERPTR_READONLY) | ||
| 294 | return -EINVAL; | ||
| 295 | |||
| 296 | /* readonly pages not tested on older hardware */ | ||
| 297 | if (rdev->family < CHIP_R600) | ||
| 298 | return -EINVAL; | ||
| 299 | |||
| 300 | down_read(&rdev->exclusive_lock); | ||
| 301 | |||
| 302 | /* create a gem object to contain this object in */ | ||
| 303 | r = radeon_gem_object_create(rdev, args->size, 0, | ||
| 304 | RADEON_GEM_DOMAIN_CPU, 0, | ||
| 305 | false, &gobj); | ||
| 306 | if (r) | ||
| 307 | goto handle_lockup; | ||
| 308 | |||
| 309 | bo = gem_to_radeon_bo(gobj); | ||
| 310 | r = radeon_ttm_tt_set_userptr(bo->tbo.ttm, args->addr, args->flags); | ||
| 311 | if (r) | ||
| 312 | goto release_object; | ||
| 313 | |||
| 314 | r = drm_gem_handle_create(filp, gobj, &handle); | ||
| 315 | /* drop reference from allocate - handle holds it now */ | ||
| 316 | drm_gem_object_unreference_unlocked(gobj); | ||
| 317 | if (r) | ||
| 318 | goto handle_lockup; | ||
| 319 | |||
| 320 | args->handle = handle; | ||
| 321 | up_read(&rdev->exclusive_lock); | ||
| 322 | return 0; | ||
| 323 | |||
| 324 | release_object: | ||
| 325 | drm_gem_object_unreference_unlocked(gobj); | ||
| 326 | |||
| 327 | handle_lockup: | ||
| 328 | up_read(&rdev->exclusive_lock); | ||
| 329 | r = radeon_gem_handle_lockup(rdev, r); | ||
| 330 | |||
