~ubuntu-branches/ubuntu/maverick/libdrm/maverick-proposed

« back to all changes in this revision

Viewing changes to nouveau/nouveau_bo.c

  • Committer: Bazaar Package Importer
  • Author(s): Timo Aaltonen
  • Date: 2010-01-09 00:00:29 UTC
  • mfrom: (1.3.3 upstream)
  • mto: (2.2.9 experimental)
  • mto: This revision was merged to the branch mainline in revision 39.
  • Revision ID: james.westby@ubuntu.com-20100109000029-yhmol07llcxuzk0c
Tags: upstream-2.4.17
ImportĀ upstreamĀ versionĀ 2.4.17

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 2007 Nouveau Project
 
3
 *
 
4
 * Permission is hereby granted, free of charge, to any person obtaining a
 
5
 * copy of this software and associated documentation files (the "Software"),
 
6
 * to deal in the Software without restriction, including without limitation
 
7
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 
8
 * and/or sell copies of the Software, and to permit persons to whom the
 
9
 * Software is furnished to do so, subject to the following conditions:
 
10
 *
 
11
 * The above copyright notice and this permission notice shall be included in
 
12
 * all copies or substantial portions of the Software.
 
13
 *
 
14
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
15
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
16
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 
17
 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 
18
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
 
19
 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 
20
 * SOFTWARE.
 
21
 */
 
22
 
 
23
#ifdef HAVE_CONFIG_H
 
24
#include <config.h>
 
25
#endif
 
26
#include <stdint.h>
 
27
#include <stdlib.h>
 
28
#include <errno.h>
 
29
#include <assert.h>
 
30
 
 
31
#include <sys/mman.h>
 
32
 
 
33
#include "nouveau_private.h"
 
34
 
 
35
int
 
36
nouveau_bo_init(struct nouveau_device *dev)
 
37
{
 
38
        return 0;
 
39
}
 
40
 
 
41
void
 
42
nouveau_bo_takedown(struct nouveau_device *dev)
 
43
{
 
44
}
 
45
 
 
46
static int
 
47
nouveau_bo_info(struct nouveau_bo_priv *nvbo, struct drm_nouveau_gem_info *arg)
 
48
{
 
49
        nvbo->handle = nvbo->base.handle = arg->handle;
 
50
        nvbo->domain = arg->domain;
 
51
        nvbo->size = arg->size;
 
52
        nvbo->offset = arg->offset;
 
53
        nvbo->map_handle = arg->map_handle;
 
54
        nvbo->base.tile_mode = arg->tile_mode;
 
55
        nvbo->base.tile_flags = arg->tile_flags;
 
56
        return 0;
 
57
}
 
58
 
 
59
static int
 
60
nouveau_bo_allocated(struct nouveau_bo_priv *nvbo)
 
61
{
 
62
        if (nvbo->sysmem || nvbo->handle)
 
63
                return 1;
 
64
        return 0;
 
65
}
 
66
 
 
67
static int
 
68
nouveau_bo_ualloc(struct nouveau_bo_priv *nvbo)
 
69
{
 
70
        if (nvbo->user || nvbo->sysmem) {
 
71
                assert(nvbo->sysmem);
 
72
                return 0;
 
73
        }
 
74
 
 
75
        nvbo->sysmem = malloc(nvbo->size);
 
76
        if (!nvbo->sysmem)
 
77
                return -ENOMEM;
 
78
 
 
79
        return 0;
 
80
}
 
81
 
 
82
static void
 
83
nouveau_bo_ufree(struct nouveau_bo_priv *nvbo)
 
84
{
 
85
        if (nvbo->sysmem) {
 
86
                if (!nvbo->user)
 
87
                        free(nvbo->sysmem);
 
88
                nvbo->sysmem = NULL;
 
89
        }
 
90
}
 
91
 
 
92
static void
 
93
nouveau_bo_kfree(struct nouveau_bo_priv *nvbo)
 
94
{
 
95
        struct nouveau_device_priv *nvdev = nouveau_device(nvbo->base.device);
 
96
        struct drm_gem_close req;
 
97
 
 
98
        if (!nvbo->handle)
 
99
                return;
 
100
 
 
101
        if (nvbo->map) {
 
102
                munmap(nvbo->map, nvbo->size);
 
103
                nvbo->map = NULL;
 
104
        }
 
105
 
 
106
        req.handle = nvbo->handle;
 
107
        nvbo->handle = 0;
 
108
        drmIoctl(nvdev->fd, DRM_IOCTL_GEM_CLOSE, &req);
 
109
}
 
110
 
 
111
static int
 
112
nouveau_bo_kalloc(struct nouveau_bo_priv *nvbo, struct nouveau_channel *chan)
 
113
{
 
114
        struct nouveau_device_priv *nvdev = nouveau_device(nvbo->base.device);
 
115
        struct drm_nouveau_gem_new req;
 
116
        struct drm_nouveau_gem_info *info = &req.info;
 
117
        int ret;
 
118
 
 
119
        if (nvbo->handle)
 
120
                return 0;
 
121
 
 
122
        req.channel_hint = chan ? chan->id : 0;
 
123
        req.align = nvbo->align;
 
124
 
 
125
 
 
126
        info->size = nvbo->size;
 
127
        info->domain = 0;
 
128
 
 
129
        if (nvbo->flags & NOUVEAU_BO_VRAM)
 
130
                info->domain |= NOUVEAU_GEM_DOMAIN_VRAM;
 
131
        if (nvbo->flags & NOUVEAU_BO_GART)
 
132
                info->domain |= NOUVEAU_GEM_DOMAIN_GART;
 
133
        if (!info->domain) {
 
134
                info->domain |= (NOUVEAU_GEM_DOMAIN_VRAM |
 
135
                                 NOUVEAU_GEM_DOMAIN_GART);
 
136
        }
 
137
 
 
138
        if (nvbo->flags & NOUVEAU_BO_MAP)
 
139
                info->domain |= NOUVEAU_GEM_DOMAIN_MAPPABLE;
 
140
 
 
141
        info->tile_mode = nvbo->base.tile_mode;
 
142
        info->tile_flags = nvbo->base.tile_flags;
 
143
 
 
144
        ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_GEM_NEW,
 
145
                                  &req, sizeof(req));
 
146
        if (ret)
 
147
                return ret;
 
148
 
 
149
        nouveau_bo_info(nvbo, &req.info);
 
150
        return 0;
 
151
}
 
152
 
 
153
static int
 
154
nouveau_bo_kmap(struct nouveau_bo_priv *nvbo)
 
155
{
 
156
        struct nouveau_device_priv *nvdev = nouveau_device(nvbo->base.device);
 
157
 
 
158
        if (nvbo->map)
 
159
                return 0;
 
160
 
 
161
        if (!nvbo->map_handle)
 
162
                return -EINVAL;
 
163
 
 
164
        nvbo->map = mmap(0, nvbo->size, PROT_READ | PROT_WRITE,
 
165
                         MAP_SHARED, nvdev->fd, nvbo->map_handle);
 
166
        if (nvbo->map == MAP_FAILED) {
 
167
                nvbo->map = NULL;
 
168
                return -errno;
 
169
        }
 
170
 
 
171
        return 0;
 
172
}
 
173
 
 
174
int
 
175
nouveau_bo_new_tile(struct nouveau_device *dev, uint32_t flags, int align,
 
176
                    int size, uint32_t tile_mode, uint32_t tile_flags,
 
177
                    struct nouveau_bo **bo)
 
178
{
 
179
        struct nouveau_bo_priv *nvbo;
 
180
        int ret;
 
181
 
 
182
        if (!dev || !bo || *bo)
 
183
                return -EINVAL;
 
184
 
 
185
        nvbo = calloc(1, sizeof(struct nouveau_bo_priv));
 
186
        if (!nvbo)
 
187
                return -ENOMEM;
 
188
        nvbo->base.device = dev;
 
189
        nvbo->base.size = size;
 
190
        nvbo->base.tile_mode = tile_mode;
 
191
        nvbo->base.tile_flags = tile_flags;
 
192
 
 
193
        nvbo->refcount = 1;
 
194
        nvbo->flags = flags;
 
195
        nvbo->size = size;
 
196
        nvbo->align = align;
 
197
 
 
198
        if (flags & (NOUVEAU_BO_VRAM | NOUVEAU_BO_GART)) {
 
199
                ret = nouveau_bo_kalloc(nvbo, NULL);
 
200
                if (ret) {
 
201
                        nouveau_bo_ref(NULL, (void *)nvbo);
 
202
                        return ret;
 
203
                }
 
204
 
 
205
                if (flags & NOUVEAU_BO_PIN) {
 
206
                        ret = nouveau_bo_pin((void *)nvbo, nvbo->flags);
 
207
                        if (ret) {
 
208
                                nouveau_bo_ref(NULL, (void *)nvbo);
 
209
                                return ret;
 
210
                        }
 
211
                }
 
212
        }
 
213
 
 
214
        *bo = &nvbo->base;
 
215
        return 0;
 
216
}
 
217
 
 
218
int
 
219
nouveau_bo_new(struct nouveau_device *dev, uint32_t flags, int align,
 
220
               int size, struct nouveau_bo **bo)
 
221
{
 
222
        uint32_t tile_flags = 0;
 
223
 
 
224
        if (flags & NOUVEAU_BO_TILED) {
 
225
                if (flags & NOUVEAU_BO_ZTILE)
 
226
                        tile_flags = 0x2800;
 
227
                else
 
228
                        tile_flags = 0x7000;
 
229
        }
 
230
 
 
231
        return nouveau_bo_new_tile(dev, flags, align, size, 0, tile_flags, bo);
 
232
}
 
233
 
 
234
int
 
235
nouveau_bo_user(struct nouveau_device *dev, void *ptr, int size,
 
236
                struct nouveau_bo **bo)
 
237
{
 
238
        struct nouveau_bo_priv *nvbo;
 
239
        int ret;
 
240
 
 
241
        ret = nouveau_bo_new(dev, NOUVEAU_BO_MAP, 0, size, bo);
 
242
        if (ret)
 
243
                return ret;
 
244
        nvbo = nouveau_bo(*bo);
 
245
 
 
246
        nvbo->sysmem = ptr;
 
247
        nvbo->user = 1;
 
248
        return 0;
 
249
}
 
250
 
 
251
int
 
252
nouveau_bo_wrap(struct nouveau_device *dev, uint32_t handle,
 
253
                struct nouveau_bo **bo)
 
254
{
 
255
        struct nouveau_device_priv *nvdev = nouveau_device(dev);
 
256
        struct drm_nouveau_gem_info req;
 
257
        struct nouveau_bo_priv *nvbo;
 
258
        int ret;
 
259
 
 
260
        ret = nouveau_bo_new(dev, 0, 0, 0, bo);
 
261
        if (ret)
 
262
                return ret;
 
263
        nvbo = nouveau_bo(*bo);
 
264
 
 
265
        req.handle = handle;
 
266
        ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_GEM_INFO,
 
267
                                  &req, sizeof(req));
 
268
        if (ret) {
 
269
                nouveau_bo_ref(NULL, bo);
 
270
                return ret;
 
271
        }
 
272
 
 
273
        nouveau_bo_info(nvbo, &req);
 
274
        nvbo->base.size = nvbo->size;
 
275
        return 0;
 
276
}
 
277
 
 
278
int
 
279
nouveau_bo_handle_get(struct nouveau_bo *bo, uint32_t *handle)
 
280
{
 
281
        struct nouveau_device_priv *nvdev = nouveau_device(bo->device);
 
282
        struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
 
283
        int ret;
 
284
 
 
285
        if (!bo || !handle)
 
286
                return -EINVAL;
 
287
 
 
288
        if (!nvbo->global_handle) {
 
289
                struct drm_gem_flink req;
 
290
 
 
291
                ret = nouveau_bo_kalloc(nvbo, NULL);
 
292
                if (ret)
 
293
                        return ret;
 
294
 
 
295
                req.handle = nvbo->handle;
 
296
                ret = drmIoctl(nvdev->fd, DRM_IOCTL_GEM_FLINK, &req);
 
297
                if (ret) {
 
298
                        nouveau_bo_kfree(nvbo);
 
299
                        return ret;
 
300
                }
 
301
 
 
302
                nvbo->global_handle = req.name;
 
303
        }
 
304
 
 
305
        *handle = nvbo->global_handle;
 
306
        return 0;
 
307
}
 
308
 
 
309
int
 
310
nouveau_bo_handle_ref(struct nouveau_device *dev, uint32_t handle,
 
311
                      struct nouveau_bo **bo)
 
312
{
 
313
        struct nouveau_device_priv *nvdev = nouveau_device(dev);
 
314
        struct nouveau_bo_priv *nvbo;
 
315
        struct drm_gem_open req;
 
316
        int ret;
 
317
 
 
318
        req.name = handle;
 
319
        ret = drmIoctl(nvdev->fd, DRM_IOCTL_GEM_OPEN, &req);
 
320
        if (ret) {
 
321
                nouveau_bo_ref(NULL, bo);
 
322
                return ret;
 
323
        }
 
324
 
 
325
        ret = nouveau_bo_wrap(dev, req.handle, bo);
 
326
        if (ret) {
 
327
                nouveau_bo_ref(NULL, bo);
 
328
                return ret;
 
329
        }
 
330
 
 
331
        nvbo = nouveau_bo(*bo);
 
332
        nvbo->base.handle = nvbo->handle;
 
333
        return 0;
 
334
 
335
 
 
336
static void
 
337
nouveau_bo_del(struct nouveau_bo **bo)
 
338
{
 
339
        struct nouveau_bo_priv *nvbo;
 
340
 
 
341
        if (!bo || !*bo)
 
342
                return;
 
343
        nvbo = nouveau_bo(*bo);
 
344
        *bo = NULL;
 
345
 
 
346
        if (--nvbo->refcount)
 
347
                return;
 
348
 
 
349
        if (nvbo->pending) {
 
350
                nvbo->pending = NULL;
 
351
                nouveau_pushbuf_flush(nvbo->pending_channel, 0);
 
352
        }
 
353
 
 
354
        nouveau_bo_ufree(nvbo);
 
355
        nouveau_bo_kfree(nvbo);
 
356
        free(nvbo);
 
357
}
 
358
 
 
359
int
 
360
nouveau_bo_ref(struct nouveau_bo *ref, struct nouveau_bo **pbo)
 
361
{
 
362
        if (!pbo)
 
363
                return -EINVAL;
 
364
 
 
365
        if (ref)
 
366
                nouveau_bo(ref)->refcount++;
 
367
 
 
368
        if (*pbo)
 
369
                nouveau_bo_del(pbo);
 
370
 
 
371
        *pbo = ref;
 
372
        return 0;
 
373
}
 
374
 
 
375
static int
 
376
nouveau_bo_wait(struct nouveau_bo *bo, int cpu_write, int no_wait, int no_block)
 
377
{
 
378
        struct nouveau_device_priv *nvdev = nouveau_device(bo->device);
 
379
        struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
 
380
        struct drm_nouveau_gem_cpu_prep req;
 
381
        int ret;
 
382
 
 
383
        if (!nvbo->global_handle && !nvbo->write_marker && !cpu_write)
 
384
                return 0;
 
385
 
 
386
        if (nvbo->pending &&
 
387
            (nvbo->pending->write_domains || cpu_write)) {
 
388
                nvbo->pending = NULL;
 
389
                nouveau_pushbuf_flush(nvbo->pending_channel, 0);
 
390
        }
 
391
 
 
392
        req.handle = nvbo->handle;
 
393
        req.flags = 0;
 
394
        if (cpu_write)
 
395
                req.flags |= NOUVEAU_GEM_CPU_PREP_WRITE;
 
396
        if (no_wait)
 
397
                req.flags |= NOUVEAU_GEM_CPU_PREP_NOWAIT;
 
398
        if (no_block)
 
399
                req.flags |= NOUVEAU_GEM_CPU_PREP_NOBLOCK;
 
400
 
 
401
        do {
 
402
                ret = drmCommandWrite(nvdev->fd, DRM_NOUVEAU_GEM_CPU_PREP,
 
403
                                      &req, sizeof(req));
 
404
        } while (ret == -EAGAIN);
 
405
        if (ret)
 
406
                return ret;
 
407
 
 
408
        if (ret == 0)
 
409
                nvbo->write_marker = 0;
 
410
        return 0;
 
411
}
 
412
 
 
413
int
 
414
nouveau_bo_map_range(struct nouveau_bo *bo, uint32_t delta, uint32_t size,
 
415
                     uint32_t flags)
 
416
{
 
417
        struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
 
418
        int ret;
 
419
 
 
420
        if (!nvbo || bo->map)
 
421
                return -EINVAL;
 
422
 
 
423
        if (!nouveau_bo_allocated(nvbo)) {
 
424
                if (nvbo->flags & (NOUVEAU_BO_VRAM | NOUVEAU_BO_GART)) {
 
425
                        ret = nouveau_bo_kalloc(nvbo, NULL);
 
426
                        if (ret)
 
427
                                return ret;
 
428
                }
 
429
 
 
430
                if (!nouveau_bo_allocated(nvbo)) {
 
431
                        ret = nouveau_bo_ualloc(nvbo);
 
432
                        if (ret)
 
433
                                return ret;
 
434
                }
 
435
        }
 
436
 
 
437
        if (nvbo->sysmem) {
 
438
                bo->map = (char *)nvbo->sysmem + delta;
 
439
        } else {
 
440
                ret = nouveau_bo_kmap(nvbo);
 
441
                if (ret)
 
442
                        return ret;
 
443
 
 
444
                if (!(flags & NOUVEAU_BO_NOSYNC)) {
 
445
                        ret = nouveau_bo_wait(bo, (flags & NOUVEAU_BO_WR),
 
446
                                              (flags & NOUVEAU_BO_NOWAIT), 0);
 
447
                        if (ret)
 
448
                                return ret;
 
449
                }
 
450
 
 
451
                bo->map = (char *)nvbo->map + delta;
 
452
        }
 
453
 
 
454
        return 0;
 
455
}
 
456
 
 
457
void
 
458
nouveau_bo_map_flush(struct nouveau_bo *bo, uint32_t delta, uint32_t size)
 
459
{
 
460
}
 
461
 
 
462
int
 
463
nouveau_bo_map(struct nouveau_bo *bo, uint32_t flags)
 
464
{
 
465
        return nouveau_bo_map_range(bo, 0, bo->size, flags);
 
466
}
 
467
 
 
468
void
 
469
nouveau_bo_unmap(struct nouveau_bo *bo)
 
470
{
 
471
        struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
 
472
 
 
473
        if (bo->map && !nvbo->sysmem) {
 
474
                struct nouveau_device_priv *nvdev = nouveau_device(bo->device);
 
475
                struct drm_nouveau_gem_cpu_fini req;
 
476
 
 
477
                req.handle = nvbo->handle;
 
478
                drmCommandWrite(nvdev->fd, DRM_NOUVEAU_GEM_CPU_FINI,
 
479
                                &req, sizeof(req));
 
480
        }
 
481
 
 
482
        bo->map = NULL;
 
483
}
 
484
 
 
485
int
 
486
nouveau_bo_pin(struct nouveau_bo *bo, uint32_t flags)
 
487
{
 
488
        struct nouveau_device_priv *nvdev = nouveau_device(bo->device);
 
489
        struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
 
490
        struct drm_nouveau_gem_pin req;
 
491
        int ret;
 
492
 
 
493
        if (nvbo->pinned)
 
494
                return 0;
 
495
 
 
496
        if (!nvbo->handle)
 
497
                return -EINVAL;
 
498
 
 
499
        /* Now force it to stay put :) */
 
500
        req.handle = nvbo->handle;
 
501
        req.domain = 0;
 
502
        if (flags & NOUVEAU_BO_VRAM)
 
503
                req.domain |= NOUVEAU_GEM_DOMAIN_VRAM;
 
504
        if (flags & NOUVEAU_BO_GART)
 
505
                req.domain |= NOUVEAU_GEM_DOMAIN_GART;
 
506
 
 
507
        ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_GEM_PIN, &req,
 
508
                                  sizeof(struct drm_nouveau_gem_pin));
 
509
        if (ret)
 
510
                return ret;
 
511
        nvbo->offset = req.offset;
 
512
        nvbo->domain = req.domain;
 
513
        nvbo->pinned = 1;
 
514
 
 
515
        /* Fill in public nouveau_bo members */
 
516
        if (nvbo->domain & NOUVEAU_GEM_DOMAIN_VRAM)
 
517
                bo->flags = NOUVEAU_BO_VRAM;
 
518
        if (nvbo->domain & NOUVEAU_GEM_DOMAIN_GART)
 
519
                bo->flags = NOUVEAU_BO_GART;
 
520
        bo->offset = nvbo->offset;
 
521
 
 
522
        return 0;
 
523
}
 
524
 
 
525
void
 
526
nouveau_bo_unpin(struct nouveau_bo *bo)
 
527
{
 
528
        struct nouveau_device_priv *nvdev = nouveau_device(bo->device);
 
529
        struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
 
530
        struct drm_nouveau_gem_unpin req;
 
531
 
 
532
        if (!nvbo->pinned)
 
533
                return;
 
534
 
 
535
        req.handle = nvbo->handle;
 
536
        drmCommandWrite(nvdev->fd, DRM_NOUVEAU_GEM_UNPIN, &req, sizeof(req));
 
537
 
 
538
        nvbo->pinned = bo->offset = bo->flags = 0;
 
539
}
 
540
 
 
541
int
 
542
nouveau_bo_busy(struct nouveau_bo *bo, uint32_t access)
 
543
{
 
544
        return nouveau_bo_wait(bo, (access & NOUVEAU_BO_WR), 1, 1);
 
545
}
 
546
 
 
547
uint32_t
 
548
nouveau_bo_pending(struct nouveau_bo *bo)
 
549
{
 
550
        struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
 
551
        uint32_t flags;
 
552
 
 
553
        if (!nvbo->pending)
 
554
                return 0;
 
555
 
 
556
        flags = 0;
 
557
        if (nvbo->pending->read_domains)
 
558
                flags |= NOUVEAU_BO_RD;
 
559
        if (nvbo->pending->write_domains)
 
560
                flags |= NOUVEAU_BO_WR;
 
561
 
 
562
        return flags;
 
563
}
 
564
 
 
565
struct drm_nouveau_gem_pushbuf_bo *
 
566
nouveau_bo_emit_buffer(struct nouveau_channel *chan, struct nouveau_bo *bo)
 
567
{
 
568
        struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(chan->pushbuf);
 
569
        struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
 
570
        struct drm_nouveau_gem_pushbuf_bo *pbbo;
 
571
        struct nouveau_bo *ref = NULL;
 
572
        int ret;
 
573
 
 
574
        if (nvbo->pending)
 
575
                return nvbo->pending;
 
576
 
 
577
        if (!nvbo->handle) {
 
578
                ret = nouveau_bo_kalloc(nvbo, chan);
 
579
                if (ret)
 
580
                        return NULL;
 
581
 
 
582
                if (nvbo->sysmem) {
 
583
                        void *sysmem_tmp = nvbo->sysmem;
 
584
 
 
585
                        nvbo->sysmem = NULL;
 
586
                        ret = nouveau_bo_map(bo, NOUVEAU_BO_WR);
 
587
                        if (ret)
 
588
                                return NULL;
 
589
                        nvbo->sysmem = sysmem_tmp;
 
590
 
 
591
                        memcpy(bo->map, nvbo->sysmem, nvbo->base.size);
 
592
                        nouveau_bo_ufree(nvbo);
 
593
                        nouveau_bo_unmap(bo);
 
594
                }
 
595
        }
 
596
 
 
597
        if (nvpb->nr_buffers >= NOUVEAU_GEM_MAX_BUFFERS)
 
598
                return NULL;
 
599
        pbbo = nvpb->buffers + nvpb->nr_buffers++;
 
600
        nvbo->pending = pbbo;
 
601
        nvbo->pending_channel = chan;
 
602
        nvbo->pending_refcnt = 0;
 
603
 
 
604
        nouveau_bo_ref(bo, &ref);
 
605
        pbbo->user_priv = (uint64_t)(unsigned long)ref;
 
606
        pbbo->handle = nvbo->handle;
 
607
        pbbo->valid_domains = NOUVEAU_GEM_DOMAIN_VRAM | NOUVEAU_GEM_DOMAIN_GART;
 
608
        pbbo->read_domains = 0;
 
609
        pbbo->write_domains = 0;
 
610
        pbbo->presumed_domain = nvbo->domain;
 
611
        pbbo->presumed_offset = nvbo->offset;
 
612
        pbbo->presumed_ok = 1;
 
613
        return pbbo;
 
614
}