Merge branch 'timers-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[pandora-kernel.git] / drivers / gpu / drm / ttm / ttm_bo_util.c
1 /**************************************************************************
2  *
3  * Copyright (c) 2007-2009 VMware, Inc., Palo Alto, CA., USA
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sub license, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the
15  * next paragraph) shall be included in all copies or substantial portions
16  * of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
22  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24  * USE OR OTHER DEALINGS IN THE SOFTWARE.
25  *
26  **************************************************************************/
27 /*
28  * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com>
29  */
30
31 #include "ttm/ttm_bo_driver.h"
32 #include "ttm/ttm_placement.h"
33 #include <linux/io.h>
34 #include <linux/highmem.h>
35 #include <linux/wait.h>
36 #include <linux/vmalloc.h>
37 #include <linux/module.h>
38
39 void ttm_bo_free_old_node(struct ttm_buffer_object *bo)
40 {
41         struct ttm_mem_reg *old_mem = &bo->mem;
42
43         if (old_mem->mm_node) {
44                 spin_lock(&bo->bdev->lru_lock);
45                 drm_mm_put_block(old_mem->mm_node);
46                 spin_unlock(&bo->bdev->lru_lock);
47         }
48         old_mem->mm_node = NULL;
49 }
50
51 int ttm_bo_move_ttm(struct ttm_buffer_object *bo,
52                     bool evict, bool no_wait, struct ttm_mem_reg *new_mem)
53 {
54         struct ttm_tt *ttm = bo->ttm;
55         struct ttm_mem_reg *old_mem = &bo->mem;
56         uint32_t save_flags = old_mem->placement;
57         int ret;
58
59         if (old_mem->mem_type != TTM_PL_SYSTEM) {
60                 ttm_tt_unbind(ttm);
61                 ttm_bo_free_old_node(bo);
62                 ttm_flag_masked(&old_mem->placement, TTM_PL_FLAG_SYSTEM,
63                                 TTM_PL_MASK_MEM);
64                 old_mem->mem_type = TTM_PL_SYSTEM;
65                 save_flags = old_mem->placement;
66         }
67
68         ret = ttm_tt_set_placement_caching(ttm, new_mem->placement);
69         if (unlikely(ret != 0))
70                 return ret;
71
72         if (new_mem->mem_type != TTM_PL_SYSTEM) {
73                 ret = ttm_tt_bind(ttm, new_mem);
74                 if (unlikely(ret != 0))
75                         return ret;
76         }
77
78         *old_mem = *new_mem;
79         new_mem->mm_node = NULL;
80         ttm_flag_masked(&save_flags, new_mem->placement, TTM_PL_MASK_MEMTYPE);
81         return 0;
82 }
83 EXPORT_SYMBOL(ttm_bo_move_ttm);
84
85 int ttm_mem_reg_ioremap(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem,
86                         void **virtual)
87 {
88         struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
89         unsigned long bus_offset;
90         unsigned long bus_size;
91         unsigned long bus_base;
92         int ret;
93         void *addr;
94
95         *virtual = NULL;
96         ret = ttm_bo_pci_offset(bdev, mem, &bus_base, &bus_offset, &bus_size);
97         if (ret || bus_size == 0)
98                 return ret;
99
100         if (!(man->flags & TTM_MEMTYPE_FLAG_NEEDS_IOREMAP))
101                 addr = (void *)(((u8 *) man->io_addr) + bus_offset);
102         else {
103                 if (mem->placement & TTM_PL_FLAG_WC)
104                         addr = ioremap_wc(bus_base + bus_offset, bus_size);
105                 else
106                         addr = ioremap_nocache(bus_base + bus_offset, bus_size);
107                 if (!addr)
108                         return -ENOMEM;
109         }
110         *virtual = addr;
111         return 0;
112 }
113
114 void ttm_mem_reg_iounmap(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem,
115                          void *virtual)
116 {
117         struct ttm_mem_type_manager *man;
118
119         man = &bdev->man[mem->mem_type];
120
121         if (virtual && (man->flags & TTM_MEMTYPE_FLAG_NEEDS_IOREMAP))
122                 iounmap(virtual);
123 }
124
125 static int ttm_copy_io_page(void *dst, void *src, unsigned long page)
126 {
127         uint32_t *dstP =
128             (uint32_t *) ((unsigned long)dst + (page << PAGE_SHIFT));
129         uint32_t *srcP =
130             (uint32_t *) ((unsigned long)src + (page << PAGE_SHIFT));
131
132         int i;
133         for (i = 0; i < PAGE_SIZE / sizeof(uint32_t); ++i)
134                 iowrite32(ioread32(srcP++), dstP++);
135         return 0;
136 }
137
138 static int ttm_copy_io_ttm_page(struct ttm_tt *ttm, void *src,
139                                 unsigned long page)
140 {
141         struct page *d = ttm_tt_get_page(ttm, page);
142         void *dst;
143
144         if (!d)
145                 return -ENOMEM;
146
147         src = (void *)((unsigned long)src + (page << PAGE_SHIFT));
148         dst = kmap(d);
149         if (!dst)
150                 return -ENOMEM;
151
152         memcpy_fromio(dst, src, PAGE_SIZE);
153         kunmap(d);
154         return 0;
155 }
156
157 static int ttm_copy_ttm_io_page(struct ttm_tt *ttm, void *dst,
158                                 unsigned long page)
159 {
160         struct page *s = ttm_tt_get_page(ttm, page);
161         void *src;
162
163         if (!s)
164                 return -ENOMEM;
165
166         dst = (void *)((unsigned long)dst + (page << PAGE_SHIFT));
167         src = kmap(s);
168         if (!src)
169                 return -ENOMEM;
170
171         memcpy_toio(dst, src, PAGE_SIZE);
172         kunmap(s);
173         return 0;
174 }
175
176 int ttm_bo_move_memcpy(struct ttm_buffer_object *bo,
177                        bool evict, bool no_wait, struct ttm_mem_reg *new_mem)
178 {
179         struct ttm_bo_device *bdev = bo->bdev;
180         struct ttm_mem_type_manager *man = &bdev->man[new_mem->mem_type];
181         struct ttm_tt *ttm = bo->ttm;
182         struct ttm_mem_reg *old_mem = &bo->mem;
183         struct ttm_mem_reg old_copy = *old_mem;
184         void *old_iomap;
185         void *new_iomap;
186         int ret;
187         uint32_t save_flags = old_mem->placement;
188         unsigned long i;
189         unsigned long page;
190         unsigned long add = 0;
191         int dir;
192
193         ret = ttm_mem_reg_ioremap(bdev, old_mem, &old_iomap);
194         if (ret)
195                 return ret;
196         ret = ttm_mem_reg_ioremap(bdev, new_mem, &new_iomap);
197         if (ret)
198                 goto out;
199
200         if (old_iomap == NULL && new_iomap == NULL)
201                 goto out2;
202         if (old_iomap == NULL && ttm == NULL)
203                 goto out2;
204
205         add = 0;
206         dir = 1;
207
208         if ((old_mem->mem_type == new_mem->mem_type) &&
209             (new_mem->mm_node->start <
210              old_mem->mm_node->start + old_mem->mm_node->size)) {
211                 dir = -1;
212                 add = new_mem->num_pages - 1;
213         }
214
215         for (i = 0; i < new_mem->num_pages; ++i) {
216                 page = i * dir + add;
217                 if (old_iomap == NULL)
218                         ret = ttm_copy_ttm_io_page(ttm, new_iomap, page);
219                 else if (new_iomap == NULL)
220                         ret = ttm_copy_io_ttm_page(ttm, old_iomap, page);
221                 else
222                         ret = ttm_copy_io_page(new_iomap, old_iomap, page);
223                 if (ret)
224                         goto out1;
225         }
226         mb();
227 out2:
228         ttm_bo_free_old_node(bo);
229
230         *old_mem = *new_mem;
231         new_mem->mm_node = NULL;
232         ttm_flag_masked(&save_flags, new_mem->placement, TTM_PL_MASK_MEMTYPE);
233
234         if ((man->flags & TTM_MEMTYPE_FLAG_FIXED) && (ttm != NULL)) {
235                 ttm_tt_unbind(ttm);
236                 ttm_tt_destroy(ttm);
237                 bo->ttm = NULL;
238         }
239
240 out1:
241         ttm_mem_reg_iounmap(bdev, new_mem, new_iomap);
242 out:
243         ttm_mem_reg_iounmap(bdev, &old_copy, old_iomap);
244         return ret;
245 }
246 EXPORT_SYMBOL(ttm_bo_move_memcpy);
247
248 static void ttm_transfered_destroy(struct ttm_buffer_object *bo)
249 {
250         kfree(bo);
251 }
252
253 /**
254  * ttm_buffer_object_transfer
255  *
256  * @bo: A pointer to a struct ttm_buffer_object.
257  * @new_obj: A pointer to a pointer to a newly created ttm_buffer_object,
258  * holding the data of @bo with the old placement.
259  *
260  * This is a utility function that may be called after an accelerated move
261  * has been scheduled. A new buffer object is created as a placeholder for
262  * the old data while it's being copied. When that buffer object is idle,
263  * it can be destroyed, releasing the space of the old placement.
264  * Returns:
265  * !0: Failure.
266  */
267
268 static int ttm_buffer_object_transfer(struct ttm_buffer_object *bo,
269                                       struct ttm_buffer_object **new_obj)
270 {
271         struct ttm_buffer_object *fbo;
272         struct ttm_bo_device *bdev = bo->bdev;
273         struct ttm_bo_driver *driver = bdev->driver;
274
275         fbo = kzalloc(sizeof(*fbo), GFP_KERNEL);
276         if (!fbo)
277                 return -ENOMEM;
278
279         *fbo = *bo;
280
281         /**
282          * Fix up members that we shouldn't copy directly:
283          * TODO: Explicit member copy would probably be better here.
284          */
285
286         spin_lock_init(&fbo->lock);
287         init_waitqueue_head(&fbo->event_queue);
288         INIT_LIST_HEAD(&fbo->ddestroy);
289         INIT_LIST_HEAD(&fbo->lru);
290         INIT_LIST_HEAD(&fbo->swap);
291         fbo->vm_node = NULL;
292
293         fbo->sync_obj = driver->sync_obj_ref(bo->sync_obj);
294         if (fbo->mem.mm_node)
295                 fbo->mem.mm_node->private = (void *)fbo;
296         kref_init(&fbo->list_kref);
297         kref_init(&fbo->kref);
298         fbo->destroy = &ttm_transfered_destroy;
299
300         *new_obj = fbo;
301         return 0;
302 }
303
304 pgprot_t ttm_io_prot(uint32_t caching_flags, pgprot_t tmp)
305 {
306 #if defined(__i386__) || defined(__x86_64__)
307         if (caching_flags & TTM_PL_FLAG_WC)
308                 tmp = pgprot_writecombine(tmp);
309         else if (boot_cpu_data.x86 > 3)
310                 tmp = pgprot_noncached(tmp);
311
312 #elif defined(__powerpc__)
313         if (!(caching_flags & TTM_PL_FLAG_CACHED)) {
314                 pgprot_val(tmp) |= _PAGE_NO_CACHE;
315                 if (caching_flags & TTM_PL_FLAG_UNCACHED)
316                         pgprot_val(tmp) |= _PAGE_GUARDED;
317         }
318 #endif
319 #if defined(__ia64__)
320         if (caching_flags & TTM_PL_FLAG_WC)
321                 tmp = pgprot_writecombine(tmp);
322         else
323                 tmp = pgprot_noncached(tmp);
324 #endif
325 #if defined(__sparc__)
326         if (!(caching_flags & TTM_PL_FLAG_CACHED))
327                 tmp = pgprot_noncached(tmp);
328 #endif
329         return tmp;
330 }
331
332 static int ttm_bo_ioremap(struct ttm_buffer_object *bo,
333                           unsigned long bus_base,
334                           unsigned long bus_offset,
335                           unsigned long bus_size,
336                           struct ttm_bo_kmap_obj *map)
337 {
338         struct ttm_bo_device *bdev = bo->bdev;
339         struct ttm_mem_reg *mem = &bo->mem;
340         struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
341
342         if (!(man->flags & TTM_MEMTYPE_FLAG_NEEDS_IOREMAP)) {
343                 map->bo_kmap_type = ttm_bo_map_premapped;
344                 map->virtual = (void *)(((u8 *) man->io_addr) + bus_offset);
345         } else {
346                 map->bo_kmap_type = ttm_bo_map_iomap;
347                 if (mem->placement & TTM_PL_FLAG_WC)
348                         map->virtual = ioremap_wc(bus_base + bus_offset,
349                                                   bus_size);
350                 else
351                         map->virtual = ioremap_nocache(bus_base + bus_offset,
352                                                        bus_size);
353         }
354         return (!map->virtual) ? -ENOMEM : 0;
355 }
356
357 static int ttm_bo_kmap_ttm(struct ttm_buffer_object *bo,
358                            unsigned long start_page,
359                            unsigned long num_pages,
360                            struct ttm_bo_kmap_obj *map)
361 {
362         struct ttm_mem_reg *mem = &bo->mem; pgprot_t prot;
363         struct ttm_tt *ttm = bo->ttm;
364         struct page *d;
365         int i;
366
367         BUG_ON(!ttm);
368         if (num_pages == 1 && (mem->placement & TTM_PL_FLAG_CACHED)) {
369                 /*
370                  * We're mapping a single page, and the desired
371                  * page protection is consistent with the bo.
372                  */
373
374                 map->bo_kmap_type = ttm_bo_map_kmap;
375                 map->page = ttm_tt_get_page(ttm, start_page);
376                 map->virtual = kmap(map->page);
377         } else {
378             /*
379              * Populate the part we're mapping;
380              */
381                 for (i = start_page; i < start_page + num_pages; ++i) {
382                         d = ttm_tt_get_page(ttm, i);
383                         if (!d)
384                                 return -ENOMEM;
385                 }
386
387                 /*
388                  * We need to use vmap to get the desired page protection
389                  * or to make the buffer object look contigous.
390                  */
391                 prot = (mem->placement & TTM_PL_FLAG_CACHED) ?
392                         PAGE_KERNEL :
393                         ttm_io_prot(mem->placement, PAGE_KERNEL);
394                 map->bo_kmap_type = ttm_bo_map_vmap;
395                 map->virtual = vmap(ttm->pages + start_page, num_pages,
396                                     0, prot);
397         }
398         return (!map->virtual) ? -ENOMEM : 0;
399 }
400
401 int ttm_bo_kmap(struct ttm_buffer_object *bo,
402                 unsigned long start_page, unsigned long num_pages,
403                 struct ttm_bo_kmap_obj *map)
404 {
405         int ret;
406         unsigned long bus_base;
407         unsigned long bus_offset;
408         unsigned long bus_size;
409
410         BUG_ON(!list_empty(&bo->swap));
411         map->virtual = NULL;
412         if (num_pages > bo->num_pages)
413                 return -EINVAL;
414         if (start_page > bo->num_pages)
415                 return -EINVAL;
416 #if 0
417         if (num_pages > 1 && !DRM_SUSER(DRM_CURPROC))
418                 return -EPERM;
419 #endif
420         ret = ttm_bo_pci_offset(bo->bdev, &bo->mem, &bus_base,
421                                 &bus_offset, &bus_size);
422         if (ret)
423                 return ret;
424         if (bus_size == 0) {
425                 return ttm_bo_kmap_ttm(bo, start_page, num_pages, map);
426         } else {
427                 bus_offset += start_page << PAGE_SHIFT;
428                 bus_size = num_pages << PAGE_SHIFT;
429                 return ttm_bo_ioremap(bo, bus_base, bus_offset, bus_size, map);
430         }
431 }
432 EXPORT_SYMBOL(ttm_bo_kmap);
433
434 void ttm_bo_kunmap(struct ttm_bo_kmap_obj *map)
435 {
436         if (!map->virtual)
437                 return;
438         switch (map->bo_kmap_type) {
439         case ttm_bo_map_iomap:
440                 iounmap(map->virtual);
441                 break;
442         case ttm_bo_map_vmap:
443                 vunmap(map->virtual);
444                 break;
445         case ttm_bo_map_kmap:
446                 kunmap(map->page);
447                 break;
448         case ttm_bo_map_premapped:
449                 break;
450         default:
451                 BUG();
452         }
453         map->virtual = NULL;
454         map->page = NULL;
455 }
456 EXPORT_SYMBOL(ttm_bo_kunmap);
457
458 int ttm_bo_pfn_prot(struct ttm_buffer_object *bo,
459                     unsigned long dst_offset,
460                     unsigned long *pfn, pgprot_t *prot)
461 {
462         struct ttm_mem_reg *mem = &bo->mem;
463         struct ttm_bo_device *bdev = bo->bdev;
464         unsigned long bus_offset;
465         unsigned long bus_size;
466         unsigned long bus_base;
467         int ret;
468         ret = ttm_bo_pci_offset(bdev, mem, &bus_base, &bus_offset,
469                         &bus_size);
470         if (ret)
471                 return -EINVAL;
472         if (bus_size != 0)
473                 *pfn = (bus_base + bus_offset + dst_offset) >> PAGE_SHIFT;
474         else
475                 if (!bo->ttm)
476                         return -EINVAL;
477                 else
478                         *pfn = page_to_pfn(ttm_tt_get_page(bo->ttm,
479                                                            dst_offset >>
480                                                            PAGE_SHIFT));
481         *prot = (mem->placement & TTM_PL_FLAG_CACHED) ?
482                 PAGE_KERNEL : ttm_io_prot(mem->placement, PAGE_KERNEL);
483
484         return 0;
485 }
486
487 int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo,
488                               void *sync_obj,
489                               void *sync_obj_arg,
490                               bool evict, bool no_wait,
491                               struct ttm_mem_reg *new_mem)
492 {
493         struct ttm_bo_device *bdev = bo->bdev;
494         struct ttm_bo_driver *driver = bdev->driver;
495         struct ttm_mem_type_manager *man = &bdev->man[new_mem->mem_type];
496         struct ttm_mem_reg *old_mem = &bo->mem;
497         int ret;
498         uint32_t save_flags = old_mem->placement;
499         struct ttm_buffer_object *ghost_obj;
500         void *tmp_obj = NULL;
501
502         spin_lock(&bo->lock);
503         if (bo->sync_obj) {
504                 tmp_obj = bo->sync_obj;
505                 bo->sync_obj = NULL;
506         }
507         bo->sync_obj = driver->sync_obj_ref(sync_obj);
508         bo->sync_obj_arg = sync_obj_arg;
509         if (evict) {
510                 ret = ttm_bo_wait(bo, false, false, false);
511                 spin_unlock(&bo->lock);
512                 driver->sync_obj_unref(&bo->sync_obj);
513
514                 if (ret)
515                         return ret;
516
517                 ttm_bo_free_old_node(bo);
518                 if ((man->flags & TTM_MEMTYPE_FLAG_FIXED) &&
519                     (bo->ttm != NULL)) {
520                         ttm_tt_unbind(bo->ttm);
521                         ttm_tt_destroy(bo->ttm);
522                         bo->ttm = NULL;
523                 }
524         } else {
525                 /**
526                  * This should help pipeline ordinary buffer moves.
527                  *
528                  * Hang old buffer memory on a new buffer object,
529                  * and leave it to be released when the GPU
530                  * operation has completed.
531                  */
532
533                 set_bit(TTM_BO_PRIV_FLAG_MOVING, &bo->priv_flags);
534                 spin_unlock(&bo->lock);
535
536                 ret = ttm_buffer_object_transfer(bo, &ghost_obj);
537                 if (ret)
538                         return ret;
539
540                 /**
541                  * If we're not moving to fixed memory, the TTM object
542                  * needs to stay alive. Otherwhise hang it on the ghost
543                  * bo to be unbound and destroyed.
544                  */
545
546                 if (!(man->flags & TTM_MEMTYPE_FLAG_FIXED))
547                         ghost_obj->ttm = NULL;
548                 else
549                         bo->ttm = NULL;
550
551                 ttm_bo_unreserve(ghost_obj);
552                 ttm_bo_unref(&ghost_obj);
553         }
554
555         *old_mem = *new_mem;
556         new_mem->mm_node = NULL;
557         ttm_flag_masked(&save_flags, new_mem->placement, TTM_PL_MASK_MEMTYPE);
558         return 0;
559 }
560 EXPORT_SYMBOL(ttm_bo_move_accel_cleanup);