]> Pileus Git - ~andy/linux/blob - drivers/gpu/drm/radeon/radeon_gem.c
Merge branch 'clps711x/cleanup' into next/cleanup
[~andy/linux] / drivers / gpu / drm / radeon / radeon_gem.c
1 /*
2  * Copyright 2008 Advanced Micro Devices, Inc.
3  * Copyright 2008 Red Hat Inc.
4  * Copyright 2009 Jerome Glisse.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22  * OTHER DEALINGS IN THE SOFTWARE.
23  *
24  * Authors: Dave Airlie
25  *          Alex Deucher
26  *          Jerome Glisse
27  */
28 #include "drmP.h"
29 #include "drm.h"
30 #include "radeon_drm.h"
31 #include "radeon.h"
32
33 int radeon_gem_object_init(struct drm_gem_object *obj)
34 {
35         BUG();
36
37         return 0;
38 }
39
40 void radeon_gem_object_free(struct drm_gem_object *gobj)
41 {
42         struct radeon_bo *robj = gem_to_radeon_bo(gobj);
43
44         if (robj) {
45                 radeon_bo_unref(&robj);
46         }
47 }
48
49 int radeon_gem_object_create(struct radeon_device *rdev, int size,
50                                 int alignment, int initial_domain,
51                                 bool discardable, bool kernel,
52                                 struct drm_gem_object **obj)
53 {
54         struct radeon_bo *robj;
55         int r;
56
57         *obj = NULL;
58         /* At least align on page size */
59         if (alignment < PAGE_SIZE) {
60                 alignment = PAGE_SIZE;
61         }
62         r = radeon_bo_create(rdev, size, alignment, kernel, initial_domain, &robj);
63         if (r) {
64                 if (r != -ERESTARTSYS)
65                         DRM_ERROR("Failed to allocate GEM object (%d, %d, %u, %d)\n",
66                                   size, initial_domain, alignment, r);
67                 return r;
68         }
69         *obj = &robj->gem_base;
70
71         mutex_lock(&rdev->gem.mutex);
72         list_add_tail(&robj->list, &rdev->gem.objects);
73         mutex_unlock(&rdev->gem.mutex);
74
75         return 0;
76 }
77
78 int radeon_gem_set_domain(struct drm_gem_object *gobj,
79                           uint32_t rdomain, uint32_t wdomain)
80 {
81         struct radeon_bo *robj;
82         uint32_t domain;
83         int r;
84
85         /* FIXME: reeimplement */
86         robj = gem_to_radeon_bo(gobj);
87         /* work out where to validate the buffer to */
88         domain = wdomain;
89         if (!domain) {
90                 domain = rdomain;
91         }
92         if (!domain) {
93                 /* Do nothings */
94                 printk(KERN_WARNING "Set domain withou domain !\n");
95                 return 0;
96         }
97         if (domain == RADEON_GEM_DOMAIN_CPU) {
98                 /* Asking for cpu access wait for object idle */
99                 r = radeon_bo_wait(robj, NULL, false);
100                 if (r) {
101                         printk(KERN_ERR "Failed to wait for object !\n");
102                         return r;
103                 }
104         }
105         return 0;
106 }
107
108 int radeon_gem_init(struct radeon_device *rdev)
109 {
110         INIT_LIST_HEAD(&rdev->gem.objects);
111         return 0;
112 }
113
114 void radeon_gem_fini(struct radeon_device *rdev)
115 {
116         radeon_bo_force_delete(rdev);
117 }
118
119 /*
120  * Call from drm_gem_handle_create which appear in both new and open ioctl
121  * case.
122  */
123 int radeon_gem_object_open(struct drm_gem_object *obj, struct drm_file *file_priv)
124 {
125         return 0;
126 }
127
128 void radeon_gem_object_close(struct drm_gem_object *obj,
129                              struct drm_file *file_priv)
130 {
131         struct radeon_bo *rbo = gem_to_radeon_bo(obj);
132         struct radeon_device *rdev = rbo->rdev;
133         struct radeon_fpriv *fpriv = file_priv->driver_priv;
134         struct radeon_vm *vm = &fpriv->vm;
135         struct radeon_bo_va *bo_va, *tmp;
136
137         if (rdev->family < CHIP_CAYMAN) {
138                 return;
139         }
140
141         if (radeon_bo_reserve(rbo, false)) {
142                 return;
143         }
144         list_for_each_entry_safe(bo_va, tmp, &rbo->va, bo_list) {
145                 if (bo_va->vm == vm) {
146                         /* remove from this vm address space */
147                         mutex_lock(&vm->mutex);
148                         list_del(&bo_va->vm_list);
149                         mutex_unlock(&vm->mutex);
150                         list_del(&bo_va->bo_list);
151                         kfree(bo_va);
152                 }
153         }
154         radeon_bo_unreserve(rbo);
155 }
156
157
158 /*
159  * GEM ioctls.
160  */
161 int radeon_gem_info_ioctl(struct drm_device *dev, void *data,
162                           struct drm_file *filp)
163 {
164         struct radeon_device *rdev = dev->dev_private;
165         struct drm_radeon_gem_info *args = data;
166         struct ttm_mem_type_manager *man;
167         unsigned i;
168
169         man = &rdev->mman.bdev.man[TTM_PL_VRAM];
170
171         args->vram_size = rdev->mc.real_vram_size;
172         args->vram_visible = (u64)man->size << PAGE_SHIFT;
173         if (rdev->stollen_vga_memory)
174                 args->vram_visible -= radeon_bo_size(rdev->stollen_vga_memory);
175         args->vram_visible -= radeon_fbdev_total_size(rdev);
176         args->gart_size = rdev->mc.gtt_size - 4096 - RADEON_IB_POOL_SIZE*64*1024;
177         for(i = 0; i < RADEON_NUM_RINGS; ++i)
178                 args->gart_size -= rdev->ring[i].ring_size;
179         return 0;
180 }
181
182 int radeon_gem_pread_ioctl(struct drm_device *dev, void *data,
183                            struct drm_file *filp)
184 {
185         /* TODO: implement */
186         DRM_ERROR("unimplemented %s\n", __func__);
187         return -ENOSYS;
188 }
189
190 int radeon_gem_pwrite_ioctl(struct drm_device *dev, void *data,
191                             struct drm_file *filp)
192 {
193         /* TODO: implement */
194         DRM_ERROR("unimplemented %s\n", __func__);
195         return -ENOSYS;
196 }
197
198 int radeon_gem_create_ioctl(struct drm_device *dev, void *data,
199                             struct drm_file *filp)
200 {
201         struct radeon_device *rdev = dev->dev_private;
202         struct drm_radeon_gem_create *args = data;
203         struct drm_gem_object *gobj;
204         uint32_t handle;
205         int r;
206
207         /* create a gem object to contain this object in */
208         args->size = roundup(args->size, PAGE_SIZE);
209         r = radeon_gem_object_create(rdev, args->size, args->alignment,
210                                         args->initial_domain, false,
211                                         false, &gobj);
212         if (r) {
213                 return r;
214         }
215         r = drm_gem_handle_create(filp, gobj, &handle);
216         /* drop reference from allocate - handle holds it now */
217         drm_gem_object_unreference_unlocked(gobj);
218         if (r) {
219                 return r;
220         }
221         args->handle = handle;
222         return 0;
223 }
224
225 int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data,
226                                 struct drm_file *filp)
227 {
228         /* transition the BO to a domain -
229          * just validate the BO into a certain domain */
230         struct drm_radeon_gem_set_domain *args = data;
231         struct drm_gem_object *gobj;
232         struct radeon_bo *robj;
233         int r;
234
235         /* for now if someone requests domain CPU -
236          * just make sure the buffer is finished with */
237
238         /* just do a BO wait for now */
239         gobj = drm_gem_object_lookup(dev, filp, args->handle);
240         if (gobj == NULL) {
241                 return -ENOENT;
242         }
243         robj = gem_to_radeon_bo(gobj);
244
245         r = radeon_gem_set_domain(gobj, args->read_domains, args->write_domain);
246
247         drm_gem_object_unreference_unlocked(gobj);
248         return r;
249 }
250
251 int radeon_mode_dumb_mmap(struct drm_file *filp,
252                           struct drm_device *dev,
253                           uint32_t handle, uint64_t *offset_p)
254 {
255         struct drm_gem_object *gobj;
256         struct radeon_bo *robj;
257
258         gobj = drm_gem_object_lookup(dev, filp, handle);
259         if (gobj == NULL) {
260                 return -ENOENT;
261         }
262         robj = gem_to_radeon_bo(gobj);
263         *offset_p = radeon_bo_mmap_offset(robj);
264         drm_gem_object_unreference_unlocked(gobj);
265         return 0;
266 }
267
268 int radeon_gem_mmap_ioctl(struct drm_device *dev, void *data,
269                           struct drm_file *filp)
270 {
271         struct drm_radeon_gem_mmap *args = data;
272
273         return radeon_mode_dumb_mmap(filp, dev, args->handle, &args->addr_ptr);
274 }
275
276 int radeon_gem_busy_ioctl(struct drm_device *dev, void *data,
277                           struct drm_file *filp)
278 {
279         struct drm_radeon_gem_busy *args = data;
280         struct drm_gem_object *gobj;
281         struct radeon_bo *robj;
282         int r;
283         uint32_t cur_placement = 0;
284
285         gobj = drm_gem_object_lookup(dev, filp, args->handle);
286         if (gobj == NULL) {
287                 return -ENOENT;
288         }
289         robj = gem_to_radeon_bo(gobj);
290         r = radeon_bo_wait(robj, &cur_placement, true);
291         switch (cur_placement) {
292         case TTM_PL_VRAM:
293                 args->domain = RADEON_GEM_DOMAIN_VRAM;
294                 break;
295         case TTM_PL_TT:
296                 args->domain = RADEON_GEM_DOMAIN_GTT;
297                 break;
298         case TTM_PL_SYSTEM:
299                 args->domain = RADEON_GEM_DOMAIN_CPU;
300         default:
301                 break;
302         }
303         drm_gem_object_unreference_unlocked(gobj);
304         return r;
305 }
306
307 int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data,
308                               struct drm_file *filp)
309 {
310         struct drm_radeon_gem_wait_idle *args = data;
311         struct drm_gem_object *gobj;
312         struct radeon_bo *robj;
313         int r;
314
315         gobj = drm_gem_object_lookup(dev, filp, args->handle);
316         if (gobj == NULL) {
317                 return -ENOENT;
318         }
319         robj = gem_to_radeon_bo(gobj);
320         r = radeon_bo_wait(robj, NULL, false);
321         /* callback hw specific functions if any */
322         if (robj->rdev->asic->ioctl_wait_idle)
323                 robj->rdev->asic->ioctl_wait_idle(robj->rdev, robj);
324         drm_gem_object_unreference_unlocked(gobj);
325         return r;
326 }
327
328 int radeon_gem_set_tiling_ioctl(struct drm_device *dev, void *data,
329                                 struct drm_file *filp)
330 {
331         struct drm_radeon_gem_set_tiling *args = data;
332         struct drm_gem_object *gobj;
333         struct radeon_bo *robj;
334         int r = 0;
335
336         DRM_DEBUG("%d \n", args->handle);
337         gobj = drm_gem_object_lookup(dev, filp, args->handle);
338         if (gobj == NULL)
339                 return -ENOENT;
340         robj = gem_to_radeon_bo(gobj);
341         r = radeon_bo_set_tiling_flags(robj, args->tiling_flags, args->pitch);
342         drm_gem_object_unreference_unlocked(gobj);
343         return r;
344 }
345
346 int radeon_gem_get_tiling_ioctl(struct drm_device *dev, void *data,
347                                 struct drm_file *filp)
348 {
349         struct drm_radeon_gem_get_tiling *args = data;
350         struct drm_gem_object *gobj;
351         struct radeon_bo *rbo;
352         int r = 0;
353
354         DRM_DEBUG("\n");
355         gobj = drm_gem_object_lookup(dev, filp, args->handle);
356         if (gobj == NULL)
357                 return -ENOENT;
358         rbo = gem_to_radeon_bo(gobj);
359         r = radeon_bo_reserve(rbo, false);
360         if (unlikely(r != 0))
361                 goto out;
362         radeon_bo_get_tiling_flags(rbo, &args->tiling_flags, &args->pitch);
363         radeon_bo_unreserve(rbo);
364 out:
365         drm_gem_object_unreference_unlocked(gobj);
366         return r;
367 }
368
369 int radeon_gem_va_ioctl(struct drm_device *dev, void *data,
370                           struct drm_file *filp)
371 {
372         struct drm_radeon_gem_va *args = data;
373         struct drm_gem_object *gobj;
374         struct radeon_device *rdev = dev->dev_private;
375         struct radeon_fpriv *fpriv = filp->driver_priv;
376         struct radeon_bo *rbo;
377         struct radeon_bo_va *bo_va;
378         u32 invalid_flags;
379         int r = 0;
380
381         if (!rdev->vm_manager.enabled) {
382                 args->operation = RADEON_VA_RESULT_ERROR;
383                 return -ENOTTY;
384         }
385
386         /* !! DONT REMOVE !!
387          * We don't support vm_id yet, to be sure we don't have have broken
388          * userspace, reject anyone trying to use non 0 value thus moving
389          * forward we can use those fields without breaking existant userspace
390          */
391         if (args->vm_id) {
392                 args->operation = RADEON_VA_RESULT_ERROR;
393                 return -EINVAL;
394         }
395
396         if (args->offset < RADEON_VA_RESERVED_SIZE) {
397                 dev_err(&dev->pdev->dev,
398                         "offset 0x%lX is in reserved area 0x%X\n",
399                         (unsigned long)args->offset,
400                         RADEON_VA_RESERVED_SIZE);
401                 args->operation = RADEON_VA_RESULT_ERROR;
402                 return -EINVAL;
403         }
404
405         /* don't remove, we need to enforce userspace to set the snooped flag
406          * otherwise we will endup with broken userspace and we won't be able
407          * to enable this feature without adding new interface
408          */
409         invalid_flags = RADEON_VM_PAGE_VALID | RADEON_VM_PAGE_SYSTEM;
410         if ((args->flags & invalid_flags)) {
411                 dev_err(&dev->pdev->dev, "invalid flags 0x%08X vs 0x%08X\n",
412                         args->flags, invalid_flags);
413                 args->operation = RADEON_VA_RESULT_ERROR;
414                 return -EINVAL;
415         }
416         if (!(args->flags & RADEON_VM_PAGE_SNOOPED)) {
417                 dev_err(&dev->pdev->dev, "only supported snooped mapping for now\n");
418                 args->operation = RADEON_VA_RESULT_ERROR;
419                 return -EINVAL;
420         }
421
422         switch (args->operation) {
423         case RADEON_VA_MAP:
424         case RADEON_VA_UNMAP:
425                 break;
426         default:
427                 dev_err(&dev->pdev->dev, "unsupported operation %d\n",
428                         args->operation);
429                 args->operation = RADEON_VA_RESULT_ERROR;
430                 return -EINVAL;
431         }
432
433         gobj = drm_gem_object_lookup(dev, filp, args->handle);
434         if (gobj == NULL) {
435                 args->operation = RADEON_VA_RESULT_ERROR;
436                 return -ENOENT;
437         }
438         rbo = gem_to_radeon_bo(gobj);
439         r = radeon_bo_reserve(rbo, false);
440         if (r) {
441                 args->operation = RADEON_VA_RESULT_ERROR;
442                 drm_gem_object_unreference_unlocked(gobj);
443                 return r;
444         }
445         switch (args->operation) {
446         case RADEON_VA_MAP:
447                 bo_va = radeon_bo_va(rbo, &fpriv->vm);
448                 if (bo_va) {
449                         args->operation = RADEON_VA_RESULT_VA_EXIST;
450                         args->offset = bo_va->soffset;
451                         goto out;
452                 }
453                 r = radeon_vm_bo_add(rdev, &fpriv->vm, rbo,
454                                      args->offset, args->flags);
455                 break;
456         case RADEON_VA_UNMAP:
457                 r = radeon_vm_bo_rmv(rdev, &fpriv->vm, rbo);
458                 break;
459         default:
460                 break;
461         }
462         args->operation = RADEON_VA_RESULT_OK;
463         if (r) {
464                 args->operation = RADEON_VA_RESULT_ERROR;
465         }
466 out:
467         radeon_bo_unreserve(rbo);
468         drm_gem_object_unreference_unlocked(gobj);
469         return r;
470 }
471
472 int radeon_mode_dumb_create(struct drm_file *file_priv,
473                             struct drm_device *dev,
474                             struct drm_mode_create_dumb *args)
475 {
476         struct radeon_device *rdev = dev->dev_private;
477         struct drm_gem_object *gobj;
478         uint32_t handle;
479         int r;
480
481         args->pitch = radeon_align_pitch(rdev, args->width, args->bpp, 0) * ((args->bpp + 1) / 8);
482         args->size = args->pitch * args->height;
483         args->size = ALIGN(args->size, PAGE_SIZE);
484
485         r = radeon_gem_object_create(rdev, args->size, 0,
486                                      RADEON_GEM_DOMAIN_VRAM,
487                                      false, ttm_bo_type_device,
488                                      &gobj);
489         if (r)
490                 return -ENOMEM;
491
492         r = drm_gem_handle_create(file_priv, gobj, &handle);
493         /* drop reference from allocate - handle holds it now */
494         drm_gem_object_unreference_unlocked(gobj);
495         if (r) {
496                 return r;
497         }
498         args->handle = handle;
499         return 0;
500 }
501
502 int radeon_mode_dumb_destroy(struct drm_file *file_priv,
503                              struct drm_device *dev,
504                              uint32_t handle)
505 {
506         return drm_gem_handle_delete(file_priv, handle);
507 }