]> git.karo-electronics.de Git - mv-sheeva.git/blob - drivers/gpu/drm/nouveau/nouveau_object.c
drm/nv50: tidy up PCIEGART implementation
[mv-sheeva.git] / drivers / gpu / drm / nouveau / nouveau_object.c
1 /*
2  * Copyright (C) 2006 Ben Skeggs.
3  *
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a 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, sublicense, 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
16  * portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21  * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  *
26  */
27
28 /*
29  * Authors:
30  *   Ben Skeggs <darktama@iinet.net.au>
31  */
32
33 #include "drmP.h"
34 #include "drm.h"
35 #include "nouveau_drv.h"
36 #include "nouveau_drm.h"
37 #include "nouveau_ramht.h"
38 #include "nouveau_vm.h"
39
40 struct nouveau_gpuobj_method {
41         struct list_head head;
42         u32 mthd;
43         int (*exec)(struct nouveau_channel *, u32 class, u32 mthd, u32 data);
44 };
45
46 struct nouveau_gpuobj_class {
47         struct list_head head;
48         struct list_head methods;
49         u32 id;
50         u32 engine;
51 };
52
53 int
54 nouveau_gpuobj_class_new(struct drm_device *dev, u32 class, u32 engine)
55 {
56         struct drm_nouveau_private *dev_priv = dev->dev_private;
57         struct nouveau_gpuobj_class *oc;
58
59         oc = kzalloc(sizeof(*oc), GFP_KERNEL);
60         if (!oc)
61                 return -ENOMEM;
62
63         INIT_LIST_HEAD(&oc->methods);
64         oc->id = class;
65         oc->engine = engine;
66         list_add(&oc->head, &dev_priv->classes);
67         return 0;
68 }
69
70 int
71 nouveau_gpuobj_mthd_new(struct drm_device *dev, u32 class, u32 mthd,
72                         int (*exec)(struct nouveau_channel *, u32, u32, u32))
73 {
74         struct drm_nouveau_private *dev_priv = dev->dev_private;
75         struct nouveau_gpuobj_method *om;
76         struct nouveau_gpuobj_class *oc;
77
78         list_for_each_entry(oc, &dev_priv->classes, head) {
79                 if (oc->id == class)
80                         goto found;
81         }
82
83         return -EINVAL;
84
85 found:
86         om = kzalloc(sizeof(*om), GFP_KERNEL);
87         if (!om)
88                 return -ENOMEM;
89
90         om->mthd = mthd;
91         om->exec = exec;
92         list_add(&om->head, &oc->methods);
93         return 0;
94 }
95
96 int
97 nouveau_gpuobj_mthd_call(struct nouveau_channel *chan,
98                          u32 class, u32 mthd, u32 data)
99 {
100         struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
101         struct nouveau_gpuobj_method *om;
102         struct nouveau_gpuobj_class *oc;
103
104         list_for_each_entry(oc, &dev_priv->classes, head) {
105                 if (oc->id != class)
106                         continue;
107
108                 list_for_each_entry(om, &oc->methods, head) {
109                         if (om->mthd == mthd)
110                                 return om->exec(chan, class, mthd, data);
111                 }
112         }
113
114         return -ENOENT;
115 }
116
117 int
118 nouveau_gpuobj_mthd_call2(struct drm_device *dev, int chid,
119                           u32 class, u32 mthd, u32 data)
120 {
121         struct drm_nouveau_private *dev_priv = dev->dev_private;
122         struct nouveau_channel *chan = NULL;
123         unsigned long flags;
124         int ret = -EINVAL;
125
126         spin_lock_irqsave(&dev_priv->channels.lock, flags);
127         if (chid > 0 && chid < dev_priv->engine.fifo.channels)
128                 chan = dev_priv->channels.ptr[chid];
129         if (chan)
130                 ret = nouveau_gpuobj_mthd_call(chan, class, mthd, data);
131         spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
132         return ret;
133 }
134
135 /* NVidia uses context objects to drive drawing operations.
136
137    Context objects can be selected into 8 subchannels in the FIFO,
138    and then used via DMA command buffers.
139
140    A context object is referenced by a user defined handle (CARD32). The HW
141    looks up graphics objects in a hash table in the instance RAM.
142
143    An entry in the hash table consists of 2 CARD32. The first CARD32 contains
144    the handle, the second one a bitfield, that contains the address of the
145    object in instance RAM.
146
147    The format of the second CARD32 seems to be:
148
149    NV4 to NV30:
150
151    15: 0  instance_addr >> 4
152    17:16  engine (here uses 1 = graphics)
153    28:24  channel id (here uses 0)
154    31     valid (use 1)
155
156    NV40:
157
158    15: 0  instance_addr >> 4   (maybe 19-0)
159    21:20  engine (here uses 1 = graphics)
160    I'm unsure about the other bits, but using 0 seems to work.
161
162    The key into the hash table depends on the object handle and channel id and
163    is given as:
164 */
165
166 int
167 nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,
168                    uint32_t size, int align, uint32_t flags,
169                    struct nouveau_gpuobj **gpuobj_ret)
170 {
171         struct drm_nouveau_private *dev_priv = dev->dev_private;
172         struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem;
173         struct nouveau_gpuobj *gpuobj;
174         struct drm_mm_node *ramin = NULL;
175         int ret, i;
176
177         NV_DEBUG(dev, "ch%d size=%u align=%d flags=0x%08x\n",
178                  chan ? chan->id : -1, size, align, flags);
179
180         gpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL);
181         if (!gpuobj)
182                 return -ENOMEM;
183         NV_DEBUG(dev, "gpuobj %p\n", gpuobj);
184         gpuobj->dev = dev;
185         gpuobj->flags = flags;
186         kref_init(&gpuobj->refcount);
187         gpuobj->size = size;
188
189         spin_lock(&dev_priv->ramin_lock);
190         list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);
191         spin_unlock(&dev_priv->ramin_lock);
192
193         if (chan) {
194                 ramin = drm_mm_search_free(&chan->ramin_heap, size, align, 0);
195                 if (ramin)
196                         ramin = drm_mm_get_block(ramin, size, align);
197                 if (!ramin) {
198                         nouveau_gpuobj_ref(NULL, &gpuobj);
199                         return -ENOMEM;
200                 }
201
202                 gpuobj->pinst = chan->ramin->pinst;
203                 if (gpuobj->pinst != ~0)
204                         gpuobj->pinst += ramin->start;
205
206                 gpuobj->cinst = ramin->start;
207                 gpuobj->vinst = ramin->start + chan->ramin->vinst;
208                 gpuobj->node  = ramin;
209         } else {
210                 ret = instmem->get(gpuobj, size, align);
211                 if (ret) {
212                         nouveau_gpuobj_ref(NULL, &gpuobj);
213                         return ret;
214                 }
215
216                 ret = -ENOSYS;
217                 if (!(flags & NVOBJ_FLAG_DONT_MAP))
218                         ret = instmem->map(gpuobj);
219                 if (ret)
220                         gpuobj->pinst = ~0;
221
222                 gpuobj->cinst = NVOBJ_CINST_GLOBAL;
223         }
224
225         if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) {
226                 for (i = 0; i < gpuobj->size; i += 4)
227                         nv_wo32(gpuobj, i, 0);
228                 instmem->flush(dev);
229         }
230
231
232         *gpuobj_ret = gpuobj;
233         return 0;
234 }
235
236 int
237 nouveau_gpuobj_init(struct drm_device *dev)
238 {
239         struct drm_nouveau_private *dev_priv = dev->dev_private;
240
241         NV_DEBUG(dev, "\n");
242
243         INIT_LIST_HEAD(&dev_priv->gpuobj_list);
244         INIT_LIST_HEAD(&dev_priv->classes);
245         spin_lock_init(&dev_priv->ramin_lock);
246         dev_priv->ramin_base = ~0;
247
248         return 0;
249 }
250
251 void
252 nouveau_gpuobj_takedown(struct drm_device *dev)
253 {
254         struct drm_nouveau_private *dev_priv = dev->dev_private;
255         struct nouveau_gpuobj_method *om, *tm;
256         struct nouveau_gpuobj_class *oc, *tc;
257
258         NV_DEBUG(dev, "\n");
259
260         list_for_each_entry_safe(oc, tc, &dev_priv->classes, head) {
261                 list_for_each_entry_safe(om, tm, &oc->methods, head) {
262                         list_del(&om->head);
263                         kfree(om);
264                 }
265                 list_del(&oc->head);
266                 kfree(oc);
267         }
268
269         BUG_ON(!list_empty(&dev_priv->gpuobj_list));
270 }
271
272
273 static void
274 nouveau_gpuobj_del(struct kref *ref)
275 {
276         struct nouveau_gpuobj *gpuobj =
277                 container_of(ref, struct nouveau_gpuobj, refcount);
278         struct drm_device *dev = gpuobj->dev;
279         struct drm_nouveau_private *dev_priv = dev->dev_private;
280         struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem;
281         int i;
282
283         NV_DEBUG(dev, "gpuobj %p\n", gpuobj);
284
285         if (gpuobj->node && (gpuobj->flags & NVOBJ_FLAG_ZERO_FREE)) {
286                 for (i = 0; i < gpuobj->size; i += 4)
287                         nv_wo32(gpuobj, i, 0);
288                 instmem->flush(dev);
289         }
290
291         if (gpuobj->dtor)
292                 gpuobj->dtor(dev, gpuobj);
293
294         if (gpuobj->cinst == NVOBJ_CINST_GLOBAL) {
295                 if (gpuobj->node) {
296                         instmem->unmap(gpuobj);
297                         instmem->put(gpuobj);
298                 }
299         } else {
300                 if (gpuobj->node) {
301                         spin_lock(&dev_priv->ramin_lock);
302                         drm_mm_put_block(gpuobj->node);
303                         spin_unlock(&dev_priv->ramin_lock);
304                 }
305         }
306
307         spin_lock(&dev_priv->ramin_lock);
308         list_del(&gpuobj->list);
309         spin_unlock(&dev_priv->ramin_lock);
310
311         kfree(gpuobj);
312 }
313
314 void
315 nouveau_gpuobj_ref(struct nouveau_gpuobj *ref, struct nouveau_gpuobj **ptr)
316 {
317         if (ref)
318                 kref_get(&ref->refcount);
319
320         if (*ptr)
321                 kref_put(&(*ptr)->refcount, nouveau_gpuobj_del);
322
323         *ptr = ref;
324 }
325
326 int
327 nouveau_gpuobj_new_fake(struct drm_device *dev, u32 pinst, u64 vinst,
328                         u32 size, u32 flags, struct nouveau_gpuobj **pgpuobj)
329 {
330         struct drm_nouveau_private *dev_priv = dev->dev_private;
331         struct nouveau_gpuobj *gpuobj = NULL;
332         int i;
333
334         NV_DEBUG(dev,
335                  "pinst=0x%08x vinst=0x%010llx size=0x%08x flags=0x%08x\n",
336                  pinst, vinst, size, flags);
337
338         gpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL);
339         if (!gpuobj)
340                 return -ENOMEM;
341         NV_DEBUG(dev, "gpuobj %p\n", gpuobj);
342         gpuobj->dev = dev;
343         gpuobj->flags = flags;
344         kref_init(&gpuobj->refcount);
345         gpuobj->size  = size;
346         gpuobj->pinst = pinst;
347         gpuobj->cinst = NVOBJ_CINST_GLOBAL;
348         gpuobj->vinst = vinst;
349
350         if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) {
351                 for (i = 0; i < gpuobj->size; i += 4)
352                         nv_wo32(gpuobj, i, 0);
353                 dev_priv->engine.instmem.flush(dev);
354         }
355
356         spin_lock(&dev_priv->ramin_lock);
357         list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);
358         spin_unlock(&dev_priv->ramin_lock);
359         *pgpuobj = gpuobj;
360         return 0;
361 }
362
363
364 static uint32_t
365 nouveau_gpuobj_class_instmem_size(struct drm_device *dev, int class)
366 {
367         struct drm_nouveau_private *dev_priv = dev->dev_private;
368
369         /*XXX: dodgy hack for now */
370         if (dev_priv->card_type >= NV_50)
371                 return 24;
372         if (dev_priv->card_type >= NV_40)
373                 return 32;
374         return 16;
375 }
376
377 /*
378    DMA objects are used to reference a piece of memory in the
379    framebuffer, PCI or AGP address space. Each object is 16 bytes big
380    and looks as follows:
381
382    entry[0]
383    11:0  class (seems like I can always use 0 here)
384    12    page table present?
385    13    page entry linear?
386    15:14 access: 0 rw, 1 ro, 2 wo
387    17:16 target: 0 NV memory, 1 NV memory tiled, 2 PCI, 3 AGP
388    31:20 dma adjust (bits 0-11 of the address)
389    entry[1]
390    dma limit (size of transfer)
391    entry[X]
392    1     0 readonly, 1 readwrite
393    31:12 dma frame address of the page (bits 12-31 of the address)
394    entry[N]
395    page table terminator, same value as the first pte, as does nvidia
396    rivatv uses 0xffffffff
397
398    Non linear page tables need a list of frame addresses afterwards,
399    the rivatv project has some info on this.
400
401    The method below creates a DMA object in instance RAM and returns a handle
402    to it that can be used to set up context objects.
403 */
404
405 void
406 nv50_gpuobj_dma_init(struct nouveau_gpuobj *obj, u32 offset, int class,
407                      u64 base, u64 size, int target, int access,
408                      u32 type, u32 comp)
409 {
410         struct drm_nouveau_private *dev_priv = obj->dev->dev_private;
411         struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem;
412         u32 flags0;
413
414         flags0  = (comp << 29) | (type << 22) | class;
415         flags0 |= 0x00100000;
416
417         switch (access) {
418         case NV_MEM_ACCESS_RO: flags0 |= 0x00040000; break;
419         case NV_MEM_ACCESS_RW:
420         case NV_MEM_ACCESS_WO: flags0 |= 0x00080000; break;
421         default:
422                 break;
423         }
424
425         switch (target) {
426         case NV_MEM_TARGET_VRAM:
427                 flags0 |= 0x00010000;
428                 break;
429         case NV_MEM_TARGET_PCI:
430                 flags0 |= 0x00020000;
431                 break;
432         case NV_MEM_TARGET_PCI_NOSNOOP:
433                 flags0 |= 0x00030000;
434                 break;
435         case NV_MEM_TARGET_GART:
436                 base += dev_priv->gart_info.aper_base;
437         default:
438                 flags0 &= ~0x00100000;
439                 break;
440         }
441
442         /* convert to base + limit */
443         size = (base + size) - 1;
444
445         nv_wo32(obj, offset + 0x00, flags0);
446         nv_wo32(obj, offset + 0x04, lower_32_bits(size));
447         nv_wo32(obj, offset + 0x08, lower_32_bits(base));
448         nv_wo32(obj, offset + 0x0c, upper_32_bits(size) << 24 |
449                                     upper_32_bits(base));
450         nv_wo32(obj, offset + 0x10, 0x00000000);
451         nv_wo32(obj, offset + 0x14, 0x00000000);
452
453         pinstmem->flush(obj->dev);
454 }
455
456 int
457 nv50_gpuobj_dma_new(struct nouveau_channel *chan, int class, u64 base, u64 size,
458                     int target, int access, u32 type, u32 comp,
459                     struct nouveau_gpuobj **pobj)
460 {
461         struct drm_device *dev = chan->dev;
462         int ret;
463
464         ret = nouveau_gpuobj_new(dev, chan, 24, 16, NVOBJ_FLAG_ZERO_FREE, pobj);
465         if (ret)
466                 return ret;
467
468         nv50_gpuobj_dma_init(*pobj, 0, class, base, size, target,
469                              access, type, comp);
470         return 0;
471 }
472
473 int
474 nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class, u64 base,
475                        u64 size, int access, int target,
476                        struct nouveau_gpuobj **pobj)
477 {
478         struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
479         struct drm_device *dev = chan->dev;
480         struct nouveau_gpuobj *obj;
481         u32 page_addr, flags0, flags2;
482         int ret;
483
484         if (dev_priv->card_type >= NV_50) {
485                 u32 comp = (target == NV_MEM_TARGET_VM) ? NV_MEM_COMP_VM : 0;
486                 u32 type = (target == NV_MEM_TARGET_VM) ? NV_MEM_TYPE_VM : 0;
487
488                 return nv50_gpuobj_dma_new(chan, class, base, size,
489                                            target, access, type, comp, pobj);
490         }
491
492         if (target == NV_MEM_TARGET_GART) {
493                 if (dev_priv->gart_info.type == NOUVEAU_GART_AGP) {
494                         target = NV_MEM_TARGET_PCI_NOSNOOP;
495                         base  += dev_priv->gart_info.aper_base;
496                 } else
497                 if (base != 0) {
498                         ret = nouveau_sgdma_get_page(dev, base, &page_addr);
499                         if (ret)
500                                 return ret;
501
502                         target = NV_MEM_TARGET_PCI;
503                         base   = page_addr;
504                 } else {
505                         nouveau_gpuobj_ref(dev_priv->gart_info.sg_ctxdma, pobj);
506                         return 0;
507                 }
508         }
509
510         flags0  = class;
511         flags0 |= 0x00003000; /* PT present, PT linear */
512         flags2  = 0;
513
514         switch (target) {
515         case NV_MEM_TARGET_PCI:
516                 flags0 |= 0x00020000;
517                 break;
518         case NV_MEM_TARGET_PCI_NOSNOOP:
519                 flags0 |= 0x00030000;
520                 break;
521         default:
522                 break;
523         }
524
525         switch (access) {
526         case NV_MEM_ACCESS_RO:
527                 flags0 |= 0x00004000;
528                 break;
529         case NV_MEM_ACCESS_WO:
530                 flags0 |= 0x00008000;
531         default:
532                 flags2 |= 0x00000002;
533                 break;
534         }
535
536         flags0 |= (base & 0x00000fff) << 20;
537         flags2 |= (base & 0xfffff000);
538
539         ret = nouveau_gpuobj_new(dev, chan, 16, 16, NVOBJ_FLAG_ZERO_FREE, &obj);
540         if (ret)
541                 return ret;
542
543         nv_wo32(obj, 0x00, flags0);
544         nv_wo32(obj, 0x04, size - 1);
545         nv_wo32(obj, 0x08, flags2);
546         nv_wo32(obj, 0x0c, flags2);
547
548         obj->engine = NVOBJ_ENGINE_SW;
549         obj->class  = class;
550         *pobj = obj;
551         return 0;
552 }
553
554 /* Context objects in the instance RAM have the following structure.
555  * On NV40 they are 32 byte long, on NV30 and smaller 16 bytes.
556
557    NV4 - NV30:
558
559    entry[0]
560    11:0 class
561    12   chroma key enable
562    13   user clip enable
563    14   swizzle enable
564    17:15 patch config:
565        scrcopy_and, rop_and, blend_and, scrcopy, srccopy_pre, blend_pre
566    18   synchronize enable
567    19   endian: 1 big, 0 little
568    21:20 dither mode
569    23    single step enable
570    24    patch status: 0 invalid, 1 valid
571    25    context_surface 0: 1 valid
572    26    context surface 1: 1 valid
573    27    context pattern: 1 valid
574    28    context rop: 1 valid
575    29,30 context beta, beta4
576    entry[1]
577    7:0   mono format
578    15:8  color format
579    31:16 notify instance address
580    entry[2]
581    15:0  dma 0 instance address
582    31:16 dma 1 instance address
583    entry[3]
584    dma method traps
585
586    NV40:
587    No idea what the exact format is. Here's what can be deducted:
588
589    entry[0]:
590    11:0  class  (maybe uses more bits here?)
591    17    user clip enable
592    21:19 patch config
593    25    patch status valid ?
594    entry[1]:
595    15:0  DMA notifier  (maybe 20:0)
596    entry[2]:
597    15:0  DMA 0 instance (maybe 20:0)
598    24    big endian
599    entry[3]:
600    15:0  DMA 1 instance (maybe 20:0)
601    entry[4]:
602    entry[5]:
603    set to 0?
604 */
605 static int
606 nouveau_gpuobj_sw_new(struct nouveau_channel *chan, int class,
607                       struct nouveau_gpuobj **gpuobj_ret)
608 {
609         struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
610         struct nouveau_gpuobj *gpuobj;
611
612         gpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL);
613         if (!gpuobj)
614                 return -ENOMEM;
615         gpuobj->dev = chan->dev;
616         gpuobj->engine = NVOBJ_ENGINE_SW;
617         gpuobj->class = class;
618         kref_init(&gpuobj->refcount);
619         gpuobj->cinst = 0x40;
620
621         spin_lock(&dev_priv->ramin_lock);
622         list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);
623         spin_unlock(&dev_priv->ramin_lock);
624         *gpuobj_ret = gpuobj;
625         return 0;
626 }
627
628 int
629 nouveau_gpuobj_gr_new(struct nouveau_channel *chan, u32 handle, int class)
630 {
631         struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
632         struct drm_device *dev = chan->dev;
633         struct nouveau_gpuobj_class *oc;
634         struct nouveau_gpuobj *gpuobj;
635         int ret;
636
637         NV_DEBUG(dev, "ch%d class=0x%04x\n", chan->id, class);
638
639         list_for_each_entry(oc, &dev_priv->classes, head) {
640                 if (oc->id == class)
641                         goto found;
642         }
643
644         NV_ERROR(dev, "illegal object class: 0x%x\n", class);
645         return -EINVAL;
646
647 found:
648         switch (oc->engine) {
649         case NVOBJ_ENGINE_SW:
650                 ret = nouveau_gpuobj_sw_new(chan, class, &gpuobj);
651                 if (ret)
652                         return ret;
653                 goto insert;
654         case NVOBJ_ENGINE_GR:
655                 if (dev_priv->card_type >= NV_50 && !chan->ramin_grctx) {
656                         struct nouveau_pgraph_engine *pgraph =
657                                 &dev_priv->engine.graph;
658
659                         ret = pgraph->create_context(chan);
660                         if (ret)
661                                 return ret;
662                 }
663                 break;
664         case NVOBJ_ENGINE_CRYPT:
665                 if (!chan->crypt_ctx) {
666                         struct nouveau_crypt_engine *pcrypt =
667                                 &dev_priv->engine.crypt;
668
669                         ret = pcrypt->create_context(chan);
670                         if (ret)
671                                 return ret;
672                 }
673                 break;
674         }
675
676         ret = nouveau_gpuobj_new(dev, chan,
677                                  nouveau_gpuobj_class_instmem_size(dev, class),
678                                  16,
679                                  NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE,
680                                  &gpuobj);
681         if (ret) {
682                 NV_ERROR(dev, "error creating gpuobj: %d\n", ret);
683                 return ret;
684         }
685
686         if (dev_priv->card_type >= NV_50) {
687                 nv_wo32(gpuobj,  0, class);
688                 nv_wo32(gpuobj, 20, 0x00010000);
689         } else {
690                 switch (class) {
691                 case NV_CLASS_NULL:
692                         nv_wo32(gpuobj, 0, 0x00001030);
693                         nv_wo32(gpuobj, 4, 0xFFFFFFFF);
694                         break;
695                 default:
696                         if (dev_priv->card_type >= NV_40) {
697                                 nv_wo32(gpuobj, 0, class);
698 #ifdef __BIG_ENDIAN
699                                 nv_wo32(gpuobj, 8, 0x01000000);
700 #endif
701                         } else {
702 #ifdef __BIG_ENDIAN
703                                 nv_wo32(gpuobj, 0, class | 0x00080000);
704 #else
705                                 nv_wo32(gpuobj, 0, class);
706 #endif
707                         }
708                 }
709         }
710         dev_priv->engine.instmem.flush(dev);
711
712         gpuobj->engine = oc->engine;
713         gpuobj->class  = oc->id;
714
715 insert:
716         ret = nouveau_ramht_insert(chan, handle, gpuobj);
717         if (ret)
718                 NV_ERROR(dev, "error adding gpuobj to RAMHT: %d\n", ret);
719         nouveau_gpuobj_ref(NULL, &gpuobj);
720         return ret;
721 }
722
723 static int
724 nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan)
725 {
726         struct drm_device *dev = chan->dev;
727         struct drm_nouveau_private *dev_priv = dev->dev_private;
728         uint32_t size;
729         uint32_t base;
730         int ret;
731
732         NV_DEBUG(dev, "ch%d\n", chan->id);
733
734         /* Base amount for object storage (4KiB enough?) */
735         size = 0x2000;
736         base = 0;
737
738         /* PGRAPH context */
739         size += dev_priv->engine.graph.grctx_size;
740
741         if (dev_priv->card_type == NV_50) {
742                 /* Various fixed table thingos */
743                 size += 0x1400; /* mostly unknown stuff */
744                 size += 0x4000; /* vm pd */
745                 base  = 0x6000;
746                 /* RAMHT, not sure about setting size yet, 32KiB to be safe */
747                 size += 0x8000;
748                 /* RAMFC */
749                 size += 0x1000;
750         }
751
752         ret = nouveau_gpuobj_new(dev, NULL, size, 0x1000, 0, &chan->ramin);
753         if (ret) {
754                 NV_ERROR(dev, "Error allocating channel PRAMIN: %d\n", ret);
755                 return ret;
756         }
757
758         ret = drm_mm_init(&chan->ramin_heap, base, size);
759         if (ret) {
760                 NV_ERROR(dev, "Error creating PRAMIN heap: %d\n", ret);
761                 nouveau_gpuobj_ref(NULL, &chan->ramin);
762                 return ret;
763         }
764
765         return 0;
766 }
767
768 int
769 nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
770                             uint32_t vram_h, uint32_t tt_h)
771 {
772         struct drm_device *dev = chan->dev;
773         struct drm_nouveau_private *dev_priv = dev->dev_private;
774         struct nouveau_gpuobj *vram = NULL, *tt = NULL;
775         int ret;
776
777         NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h);
778
779         /* Allocate a chunk of memory for per-channel object storage */
780         ret = nouveau_gpuobj_channel_init_pramin(chan);
781         if (ret) {
782                 NV_ERROR(dev, "init pramin\n");
783                 return ret;
784         }
785
786         /* NV50/NVC0 VM
787          *  - Allocate per-channel page-directory
788          *  - Link with shared channel VM
789          */
790         if (dev_priv->chan_vm) {
791                 u32 pgd_offs = (dev_priv->chipset == 0x50) ? 0x1400 : 0x0200;
792                 u64 vm_vinst = chan->ramin->vinst + pgd_offs;
793                 u32 vm_pinst = chan->ramin->pinst;
794
795                 if (vm_pinst != ~0)
796                         vm_pinst += pgd_offs;
797
798                 ret = nouveau_gpuobj_new_fake(dev, vm_pinst, vm_vinst, 0x4000,
799                                               0, &chan->vm_pd);
800                 if (ret)
801                         return ret;
802
803                 nouveau_vm_ref(dev_priv->chan_vm, &chan->vm, chan->vm_pd);
804         }
805
806         /* RAMHT */
807         if (dev_priv->card_type < NV_50) {
808                 nouveau_ramht_ref(dev_priv->ramht, &chan->ramht, NULL);
809         } else {
810                 struct nouveau_gpuobj *ramht = NULL;
811
812                 ret = nouveau_gpuobj_new(dev, chan, 0x8000, 16,
813                                          NVOBJ_FLAG_ZERO_ALLOC, &ramht);
814                 if (ret)
815                         return ret;
816
817                 ret = nouveau_ramht_new(dev, ramht, &chan->ramht);
818                 nouveau_gpuobj_ref(NULL, &ramht);
819                 if (ret)
820                         return ret;
821         }
822
823         /* VRAM ctxdma */
824         if (dev_priv->card_type >= NV_50) {
825                 ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
826                                              0, (1ULL << 40), NV_MEM_ACCESS_RW,
827                                              NV_MEM_TARGET_VM, &vram);
828                 if (ret) {
829                         NV_ERROR(dev, "Error creating VRAM ctxdma: %d\n", ret);
830                         return ret;
831                 }
832         } else {
833                 ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
834                                              0, dev_priv->fb_available_size,
835                                              NV_MEM_ACCESS_RW,
836                                              NV_MEM_TARGET_VRAM, &vram);
837                 if (ret) {
838                         NV_ERROR(dev, "Error creating VRAM ctxdma: %d\n", ret);
839                         return ret;
840                 }
841         }
842
843         ret = nouveau_ramht_insert(chan, vram_h, vram);
844         nouveau_gpuobj_ref(NULL, &vram);
845         if (ret) {
846                 NV_ERROR(dev, "Error adding VRAM ctxdma to RAMHT: %d\n", ret);
847                 return ret;
848         }
849
850         /* TT memory ctxdma */
851         if (dev_priv->card_type >= NV_50) {
852                 ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
853                                              0, (1ULL << 40), NV_MEM_ACCESS_RW,
854                                              NV_MEM_TARGET_VM, &tt);
855         } else {
856                 ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
857                                              0, dev_priv->gart_info.aper_size,
858                                              NV_MEM_ACCESS_RW,
859                                              NV_MEM_TARGET_GART, &tt);
860         }
861
862         if (ret) {
863                 NV_ERROR(dev, "Error creating TT ctxdma: %d\n", ret);
864                 return ret;
865         }
866
867         ret = nouveau_ramht_insert(chan, tt_h, tt);
868         nouveau_gpuobj_ref(NULL, &tt);
869         if (ret) {
870                 NV_ERROR(dev, "Error adding TT ctxdma to RAMHT: %d\n", ret);
871                 return ret;
872         }
873
874         return 0;
875 }
876
877 void
878 nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan)
879 {
880         struct drm_device *dev = chan->dev;
881
882         NV_DEBUG(dev, "ch%d\n", chan->id);
883
884         if (!chan->ramht)
885                 return;
886
887         nouveau_ramht_ref(NULL, &chan->ramht, chan);
888
889         nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd);
890         nouveau_gpuobj_ref(NULL, &chan->vm_pd);
891
892         if (chan->ramin_heap.free_stack.next)
893                 drm_mm_takedown(&chan->ramin_heap);
894         nouveau_gpuobj_ref(NULL, &chan->ramin);
895 }
896
897 int
898 nouveau_gpuobj_suspend(struct drm_device *dev)
899 {
900         struct drm_nouveau_private *dev_priv = dev->dev_private;
901         struct nouveau_gpuobj *gpuobj;
902         int i;
903
904         list_for_each_entry(gpuobj, &dev_priv->gpuobj_list, list) {
905                 if (gpuobj->cinst != NVOBJ_CINST_GLOBAL)
906                         continue;
907
908                 gpuobj->suspend = vmalloc(gpuobj->size);
909                 if (!gpuobj->suspend) {
910                         nouveau_gpuobj_resume(dev);
911                         return -ENOMEM;
912                 }
913
914                 for (i = 0; i < gpuobj->size; i += 4)
915                         gpuobj->suspend[i/4] = nv_ro32(gpuobj, i);
916         }
917
918         return 0;
919 }
920
921 void
922 nouveau_gpuobj_resume(struct drm_device *dev)
923 {
924         struct drm_nouveau_private *dev_priv = dev->dev_private;
925         struct nouveau_gpuobj *gpuobj;
926         int i;
927
928         list_for_each_entry(gpuobj, &dev_priv->gpuobj_list, list) {
929                 if (!gpuobj->suspend)
930                         continue;
931
932                 for (i = 0; i < gpuobj->size; i += 4)
933                         nv_wo32(gpuobj, i, gpuobj->suspend[i/4]);
934
935                 vfree(gpuobj->suspend);
936                 gpuobj->suspend = NULL;
937         }
938
939         dev_priv->engine.instmem.flush(dev);
940 }
941
942 int nouveau_ioctl_grobj_alloc(struct drm_device *dev, void *data,
943                               struct drm_file *file_priv)
944 {
945         struct drm_nouveau_grobj_alloc *init = data;
946         struct nouveau_channel *chan;
947         int ret;
948
949         if (init->handle == ~0)
950                 return -EINVAL;
951
952         chan = nouveau_channel_get(dev, file_priv, init->channel);
953         if (IS_ERR(chan))
954                 return PTR_ERR(chan);
955
956         if (nouveau_ramht_find(chan, init->handle)) {
957                 ret = -EEXIST;
958                 goto out;
959         }
960
961         ret = nouveau_gpuobj_gr_new(chan, init->handle, init->class);
962         if (ret) {
963                 NV_ERROR(dev, "Error creating object: %d (%d/0x%08x)\n",
964                          ret, init->channel, init->handle);
965         }
966
967 out:
968         nouveau_channel_put(&chan);
969         return ret;
970 }
971
972 int nouveau_ioctl_gpuobj_free(struct drm_device *dev, void *data,
973                               struct drm_file *file_priv)
974 {
975         struct drm_nouveau_gpuobj_free *objfree = data;
976         struct nouveau_channel *chan;
977         int ret;
978
979         chan = nouveau_channel_get(dev, file_priv, objfree->channel);
980         if (IS_ERR(chan))
981                 return PTR_ERR(chan);
982
983         /* Synchronize with the user channel */
984         nouveau_channel_idle(chan);
985
986         ret = nouveau_ramht_remove(chan, objfree->handle);
987         nouveau_channel_put(&chan);
988         return ret;
989 }
990
991 u32
992 nv_ro32(struct nouveau_gpuobj *gpuobj, u32 offset)
993 {
994         struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private;
995         struct drm_device *dev = gpuobj->dev;
996
997         if (gpuobj->pinst == ~0 || !dev_priv->ramin_available) {
998                 u64  ptr = gpuobj->vinst + offset;
999                 u32 base = ptr >> 16;
1000                 u32  val;
1001
1002                 spin_lock(&dev_priv->ramin_lock);
1003                 if (dev_priv->ramin_base != base) {
1004                         dev_priv->ramin_base = base;
1005                         nv_wr32(dev, 0x001700, dev_priv->ramin_base);
1006                 }
1007                 val = nv_rd32(dev, 0x700000 + (ptr & 0xffff));
1008                 spin_unlock(&dev_priv->ramin_lock);
1009                 return val;
1010         }
1011
1012         return nv_ri32(dev, gpuobj->pinst + offset);
1013 }
1014
1015 void
1016 nv_wo32(struct nouveau_gpuobj *gpuobj, u32 offset, u32 val)
1017 {
1018         struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private;
1019         struct drm_device *dev = gpuobj->dev;
1020
1021         if (gpuobj->pinst == ~0 || !dev_priv->ramin_available) {
1022                 u64  ptr = gpuobj->vinst + offset;
1023                 u32 base = ptr >> 16;
1024
1025                 spin_lock(&dev_priv->ramin_lock);
1026                 if (dev_priv->ramin_base != base) {
1027                         dev_priv->ramin_base = base;
1028                         nv_wr32(dev, 0x001700, dev_priv->ramin_base);
1029                 }
1030                 nv_wr32(dev, 0x700000 + (ptr & 0xffff), val);
1031                 spin_unlock(&dev_priv->ramin_lock);
1032                 return;
1033         }
1034
1035         nv_wi32(dev, gpuobj->pinst + offset, val);
1036 }