1de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák/*
2de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák * Copyright © 2011 Marek Olšák <maraeo@gmail.com>
3de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák * All Rights Reserved.
4de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák *
5de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák * Permission is hereby granted, free of charge, to any person obtaining
6de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák * a copy of this software and associated documentation files (the
7de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák * "Software"), to deal in the Software without restriction, including
8de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák * without limitation the rights to use, copy, modify, merge, publish,
9de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák * distribute, sub license, and/or sell copies of the Software, and to
10de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák * permit persons to whom the Software is furnished to do so, subject to
11de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák * the following conditions:
12de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák *
13de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
14de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
15de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
16de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS
17de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák * USE OR OTHER DEALINGS IN THE SOFTWARE.
21de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák *
22de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák * The above copyright notice and this permission notice (including the
23de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák * next paragraph) shall be included in all copies or substantial portions
24de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák * of the Software.
25de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák */
26de22d8f1eebd3245acccdb4098526ee1bf616c06Marek Olšák
276ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák#define _FILE_OFFSET_BITS 64
286ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák#include "radeon_drm_cs.h"
296ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
306ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák#include "util/u_hash_table.h"
316ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák#include "util/u_memory.h"
326ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák#include "util/u_simple_list.h"
33bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse#include "util/u_double_list.h"
346ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák#include "os/os_thread.h"
3570b1837dfb1b282ad9efcaeec4f9c8da5f9a74d8Chia-I Wu#include "os/os_mman.h"
366ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
376ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák#include "state_tracker/drm_driver.h"
386ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
396ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák#include <sys/ioctl.h>
406ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák#include <xf86drm.h>
416ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák#include <errno.h>
426ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
43bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse/*
44bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse * this are copy from radeon_drm, once an updated libdrm is released
45bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse * we should bump configure.ac requirement for it and remove the following
46bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse * field
47bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse */
486ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák#define RADEON_BO_FLAGS_MACRO_TILE  1
496ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák#define RADEON_BO_FLAGS_MICRO_TILE  2
506ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák#define RADEON_BO_FLAGS_MICRO_TILE_SQUARE 0x20
516ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
521e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák#ifndef DRM_RADEON_GEM_WAIT
53bbc320a94def6178028a4c46012c737839e1cf61Jerome Glisse#define DRM_RADEON_GEM_WAIT     0x2b
541e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák
55bbc320a94def6178028a4c46012c737839e1cf61Jerome Glisse#define RADEON_GEM_NO_WAIT      0x1
56bbc320a94def6178028a4c46012c737839e1cf61Jerome Glisse#define RADEON_GEM_USAGE_READ   0x2
57bbc320a94def6178028a4c46012c737839e1cf61Jerome Glisse#define RADEON_GEM_USAGE_WRITE  0x4
581e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák
591e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšákstruct drm_radeon_gem_wait {
60bbc320a94def6178028a4c46012c737839e1cf61Jerome Glisse    uint32_t    handle;
61bbc320a94def6178028a4c46012c737839e1cf61Jerome Glisse    uint32_t    flags;  /* one of RADEON_GEM_* */
621e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák};
631e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák
641e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák#endif
651e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák
66bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse#ifndef RADEON_VA_MAP
67bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
68bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse#define RADEON_VA_MAP               1
69bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse#define RADEON_VA_UNMAP             2
70bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
71bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse#define RADEON_VA_RESULT_OK         0
72bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse#define RADEON_VA_RESULT_ERROR      1
73bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse#define RADEON_VA_RESULT_VA_EXIST   2
74bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
75bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse#define RADEON_VM_PAGE_VALID        (1 << 0)
76bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse#define RADEON_VM_PAGE_READABLE     (1 << 1)
77bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse#define RADEON_VM_PAGE_WRITEABLE    (1 << 2)
78bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse#define RADEON_VM_PAGE_SYSTEM       (1 << 3)
79bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse#define RADEON_VM_PAGE_SNOOPED      (1 << 4)
80bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
81bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glissestruct drm_radeon_gem_va {
82bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    uint32_t    handle;
83bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    uint32_t    operation;
84bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    uint32_t    vm_id;
85bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    uint32_t    flags;
86bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    uint64_t    offset;
87bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse};
88bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
89bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse#define DRM_RADEON_GEM_VA   0x2b
90bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse#endif
91bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
92bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
931e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák
946ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšákextern const struct pb_vtbl radeon_bo_vtbl;
956ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
966ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
976ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšákstatic INLINE struct radeon_bo *radeon_bo(struct pb_buffer *bo)
986ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák{
996ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    assert(bo->vtbl == &radeon_bo_vtbl);
1006ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    return (struct radeon_bo *)bo;
1016ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák}
1026ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
103bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glissestruct radeon_bo_va_hole {
104bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    struct list_head list;
105bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    uint64_t         offset;
106bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    uint64_t         size;
107bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse};
108bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
1096ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšákstruct radeon_bomgr {
1106ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    /* Base class. */
1116ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    struct pb_manager base;
1126ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
1136ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    /* Winsys. */
1146ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    struct radeon_drm_winsys *rws;
1156ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
1166ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    /* List of buffer handles and its mutex. */
1176ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    struct util_hash_table *bo_handles;
1186ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    pipe_mutex bo_handles_mutex;
119bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    pipe_mutex bo_va_mutex;
120bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
121bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    /* is virtual address supported */
122bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    bool va;
123c25968f3e2a1b5144a2e88d15b95e5b477a55f5dMichel Dänzer    uint64_t va_offset;
124bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    struct list_head va_holes;
1256ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák};
1266ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
1276ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšákstatic INLINE struct radeon_bomgr *radeon_bomgr(struct pb_manager *mgr)
1286ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák{
1296ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    return (struct radeon_bomgr *)mgr;
1306ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák}
1316ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
1326ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšákstatic struct radeon_bo *get_radeon_bo(struct pb_buffer *_buf)
1336ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák{
1346ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    struct radeon_bo *bo = NULL;
1356ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
1366ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    if (_buf->vtbl == &radeon_bo_vtbl) {
1376ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák        bo = radeon_bo(_buf);
1386ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    } else {
139bbc320a94def6178028a4c46012c737839e1cf61Jerome Glisse        struct pb_buffer *base_buf;
140bbc320a94def6178028a4c46012c737839e1cf61Jerome Glisse        pb_size offset;
141bbc320a94def6178028a4c46012c737839e1cf61Jerome Glisse        pb_get_base_buffer(_buf, &base_buf, &offset);
1426ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
1436ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák        if (base_buf->vtbl == &radeon_bo_vtbl)
1446ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák            bo = radeon_bo(base_buf);
1456ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    }
1466ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
1476ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    return bo;
1486ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák}
1496ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
1501e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšákstatic void radeon_bo_wait(struct pb_buffer *_buf, enum radeon_bo_usage usage)
1516ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák{
1522664980760c5cf2e7dde4065f9cc8e8b865627c3Marek Olšák    struct radeon_bo *bo = get_radeon_bo(_buf);
1536ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
154b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    while (p_atomic_read(&bo->num_active_ioctls)) {
155b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák        sched_yield();
156b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    }
157b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák
158ef64da8f013691c66744064769db379e57ef95deMarek Olšák    /* XXX use this when it's ready */
159ef64da8f013691c66744064769db379e57ef95deMarek Olšák    /*if (bo->rws->info.drm_minor >= 12) {
1601e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák        struct drm_radeon_gem_wait args = {};
1611e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák        args.handle = bo->handle;
1621e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák        args.flags = usage;
1631e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák        while (drmCommandWriteRead(bo->rws->fd, DRM_RADEON_GEM_WAIT,
1641e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák                                   &args, sizeof(args)) == -EBUSY);
165ef64da8f013691c66744064769db379e57ef95deMarek Olšák    } else*/ {
1663da5196263fb2ae60483044cbd34c94270e2accdBrian Paul        struct drm_radeon_gem_wait_idle args;
1673da5196263fb2ae60483044cbd34c94270e2accdBrian Paul        memset(&args, 0, sizeof(args));
1681e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák        args.handle = bo->handle;
1691e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák        while (drmCommandWriteRead(bo->rws->fd, DRM_RADEON_GEM_WAIT_IDLE,
1701e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák                                   &args, sizeof(args)) == -EBUSY);
1711e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák    }
1726ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák}
1736ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
1741e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšákstatic boolean radeon_bo_is_busy(struct pb_buffer *_buf,
1751e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák                                 enum radeon_bo_usage usage)
1766ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák{
1772664980760c5cf2e7dde4065f9cc8e8b865627c3Marek Olšák    struct radeon_bo *bo = get_radeon_bo(_buf);
1786ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
179b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    if (p_atomic_read(&bo->num_active_ioctls)) {
180b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák        return TRUE;
181b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    }
182b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák
183ef64da8f013691c66744064769db379e57ef95deMarek Olšák    /* XXX use this when it's ready */
184ef64da8f013691c66744064769db379e57ef95deMarek Olšák    /*if (bo->rws->info.drm_minor >= 12) {
1851e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák        struct drm_radeon_gem_wait args = {};
1861e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák        args.handle = bo->handle;
1871e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák        args.flags = usage | RADEON_GEM_NO_WAIT;
1881e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák        return drmCommandWriteRead(bo->rws->fd, DRM_RADEON_GEM_WAIT,
1891e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák                                   &args, sizeof(args)) != 0;
190ef64da8f013691c66744064769db379e57ef95deMarek Olšák    } else*/ {
1913da5196263fb2ae60483044cbd34c94270e2accdBrian Paul        struct drm_radeon_gem_busy args;
1923da5196263fb2ae60483044cbd34c94270e2accdBrian Paul        memset(&args, 0, sizeof(args));
1931e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák        args.handle = bo->handle;
1941e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák        return drmCommandWriteRead(bo->rws->fd, DRM_RADEON_GEM_BUSY,
1951e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák                                   &args, sizeof(args)) != 0;
1961e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák    }
1976ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák}
1986ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
199356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glissestatic uint64_t radeon_bomgr_find_va(struct radeon_bomgr *mgr, uint64_t size, uint64_t alignment)
200bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse{
201bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    struct radeon_bo_va_hole *hole, *n;
202356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse    uint64_t offset = 0, waste = 0;
203bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
204bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    pipe_mutex_lock(mgr->bo_va_mutex);
205bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    /* first look for a hole */
206bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    LIST_FOR_EACH_ENTRY_SAFE(hole, n, &mgr->va_holes, list) {
207356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse        offset = hole->offset;
208356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse        waste = 0;
209356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse        if (alignment) {
210356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse            waste = offset % alignment;
211356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse            waste = waste ? alignment - waste : 0;
212356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse        }
213356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse        offset += waste;
214e372e53ee0ed57072322003e508b3ca4c58076beJerome Glisse        if (offset >= (hole->offset + hole->size)) {
215e372e53ee0ed57072322003e508b3ca4c58076beJerome Glisse            continue;
216e372e53ee0ed57072322003e508b3ca4c58076beJerome Glisse        }
217356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse        if (!waste && hole->size == size) {
218bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse            offset = hole->offset;
219bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse            list_del(&hole->list);
220bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse            FREE(hole);
221bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse            pipe_mutex_unlock(mgr->bo_va_mutex);
222bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse            return offset;
223bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse        }
224f5fe81daea622f8f043edc19fb61ba367b6958aaMichel Dänzer        if ((hole->size - waste) > size) {
225356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse            if (waste) {
226356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse                n = CALLOC_STRUCT(radeon_bo_va_hole);
227356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse                n->size = waste;
228356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse                n->offset = hole->offset;
229206d07625c9fd69c7d00a8722bd7390c5215bfe2Michel Dänzer                list_add(&n->list, &hole->list);
230356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse            }
231356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse            hole->size -= (size + waste);
232356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse            hole->offset += size + waste;
233bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse            pipe_mutex_unlock(mgr->bo_va_mutex);
234bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse            return offset;
235bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse        }
236f5fe81daea622f8f043edc19fb61ba367b6958aaMichel Dänzer        if ((hole->size - waste) == size) {
237f5fe81daea622f8f043edc19fb61ba367b6958aaMichel Dänzer            hole->size = waste;
238f5fe81daea622f8f043edc19fb61ba367b6958aaMichel Dänzer            pipe_mutex_unlock(mgr->bo_va_mutex);
239f5fe81daea622f8f043edc19fb61ba367b6958aaMichel Dänzer            return offset;
240f5fe81daea622f8f043edc19fb61ba367b6958aaMichel Dänzer        }
241bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    }
242bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
243bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    offset = mgr->va_offset;
244356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse    waste = 0;
245356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse    if (alignment) {
246356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse        waste = offset % alignment;
247356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse        waste = waste ? alignment - waste : 0;
248356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse    }
249a60be05284399202c7a5a7aaf4d1f8f0626aee80Michel Dänzer    if (waste) {
250a60be05284399202c7a5a7aaf4d1f8f0626aee80Michel Dänzer        n = CALLOC_STRUCT(radeon_bo_va_hole);
251a60be05284399202c7a5a7aaf4d1f8f0626aee80Michel Dänzer        n->size = waste;
252a60be05284399202c7a5a7aaf4d1f8f0626aee80Michel Dänzer        n->offset = offset;
253a60be05284399202c7a5a7aaf4d1f8f0626aee80Michel Dänzer        list_add(&n->list, &mgr->va_holes);
254a60be05284399202c7a5a7aaf4d1f8f0626aee80Michel Dänzer    }
255356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse    offset += waste;
256356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse    mgr->va_offset += size + waste;
257bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    pipe_mutex_unlock(mgr->bo_va_mutex);
258bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    return offset;
259bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse}
260bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
261bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glissestatic void radeon_bomgr_force_va(struct radeon_bomgr *mgr, uint64_t va, uint64_t size)
262bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse{
263bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    pipe_mutex_lock(mgr->bo_va_mutex);
264bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    if (va >= mgr->va_offset) {
265bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse        if (va > mgr->va_offset) {
266bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse            struct radeon_bo_va_hole *hole;
267bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse            hole = CALLOC_STRUCT(radeon_bo_va_hole);
268bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse            if (hole) {
269bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse                hole->size = va - mgr->va_offset;
270bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse                hole->offset = mgr->va_offset;
271bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse                list_add(&hole->list, &mgr->va_holes);
272bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse            }
273bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse        }
274bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse        mgr->va_offset = va + size;
275bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    } else {
276bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse        struct radeon_bo_va_hole *hole, *n;
2771f455ef5bc3c9711d9452dcc09fd849656ad8b33Michel Dänzer        uint64_t hole_end, va_end;
278bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
2791f455ef5bc3c9711d9452dcc09fd849656ad8b33Michel Dänzer        /* Prune/free all holes that fall into the range
280bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse         */
281bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse        LIST_FOR_EACH_ENTRY_SAFE(hole, n, &mgr->va_holes, list) {
2821f455ef5bc3c9711d9452dcc09fd849656ad8b33Michel Dänzer            hole_end = hole->offset + hole->size;
2831f455ef5bc3c9711d9452dcc09fd849656ad8b33Michel Dänzer            va_end = va + size;
2841f455ef5bc3c9711d9452dcc09fd849656ad8b33Michel Dänzer            if (hole->offset >= va_end || hole_end <= va)
2851f455ef5bc3c9711d9452dcc09fd849656ad8b33Michel Dänzer                continue;
2861f455ef5bc3c9711d9452dcc09fd849656ad8b33Michel Dänzer            if (hole->offset >= va && hole_end <= va_end) {
287bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse                list_del(&hole->list);
288bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse                FREE(hole);
2891f455ef5bc3c9711d9452dcc09fd849656ad8b33Michel Dänzer                continue;
290bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse            }
2911f455ef5bc3c9711d9452dcc09fd849656ad8b33Michel Dänzer            if (hole->offset >= va)
2921f455ef5bc3c9711d9452dcc09fd849656ad8b33Michel Dänzer                hole->offset = va_end;
2931f455ef5bc3c9711d9452dcc09fd849656ad8b33Michel Dänzer            else
2941f455ef5bc3c9711d9452dcc09fd849656ad8b33Michel Dänzer                hole_end = va;
2951f455ef5bc3c9711d9452dcc09fd849656ad8b33Michel Dänzer            hole->size = hole_end - hole->offset;
296bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse        }
297bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    }
298bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    pipe_mutex_unlock(mgr->bo_va_mutex);
299bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse}
300bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
301bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glissestatic void radeon_bomgr_free_va(struct radeon_bomgr *mgr, uint64_t va, uint64_t size)
302bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse{
3036d59b7f6dc3131e773e9c9729388c08a2f987364Michel Dänzer    struct radeon_bo_va_hole *hole;
3046d59b7f6dc3131e773e9c9729388c08a2f987364Michel Dänzer
305bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    pipe_mutex_lock(mgr->bo_va_mutex);
306bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    if ((va + size) == mgr->va_offset) {
307bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse        mgr->va_offset = va;
3086d59b7f6dc3131e773e9c9729388c08a2f987364Michel Dänzer        /* Delete uppermost hole if it reaches the new top */
3096d59b7f6dc3131e773e9c9729388c08a2f987364Michel Dänzer        if (!LIST_IS_EMPTY(&mgr->va_holes)) {
3106d59b7f6dc3131e773e9c9729388c08a2f987364Michel Dänzer            hole = container_of(mgr->va_holes.next, hole, list);
3116d59b7f6dc3131e773e9c9729388c08a2f987364Michel Dänzer            if ((hole->offset + hole->size) == va) {
3126d59b7f6dc3131e773e9c9729388c08a2f987364Michel Dänzer                mgr->va_offset = hole->offset;
3136d59b7f6dc3131e773e9c9729388c08a2f987364Michel Dänzer                list_del(&hole->list);
3146d59b7f6dc3131e773e9c9729388c08a2f987364Michel Dänzer                FREE(hole);
3156d59b7f6dc3131e773e9c9729388c08a2f987364Michel Dänzer            }
3166d59b7f6dc3131e773e9c9729388c08a2f987364Michel Dänzer        }
317bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    } else {
3186d59b7f6dc3131e773e9c9729388c08a2f987364Michel Dänzer        struct radeon_bo_va_hole *next;
319206d07625c9fd69c7d00a8722bd7390c5215bfe2Michel Dänzer
320206d07625c9fd69c7d00a8722bd7390c5215bfe2Michel Dänzer        hole = container_of(&mgr->va_holes, hole, list);
321206d07625c9fd69c7d00a8722bd7390c5215bfe2Michel Dänzer        LIST_FOR_EACH_ENTRY(next, &mgr->va_holes, list) {
322206d07625c9fd69c7d00a8722bd7390c5215bfe2Michel Dänzer	    if (next->offset < va)
323206d07625c9fd69c7d00a8722bd7390c5215bfe2Michel Dänzer	        break;
324206d07625c9fd69c7d00a8722bd7390c5215bfe2Michel Dänzer            hole = next;
325206d07625c9fd69c7d00a8722bd7390c5215bfe2Michel Dänzer        }
326206d07625c9fd69c7d00a8722bd7390c5215bfe2Michel Dänzer
327206d07625c9fd69c7d00a8722bd7390c5215bfe2Michel Dänzer        if (&hole->list != &mgr->va_holes) {
328206d07625c9fd69c7d00a8722bd7390c5215bfe2Michel Dänzer            /* Grow upper hole if it's adjacent */
329206d07625c9fd69c7d00a8722bd7390c5215bfe2Michel Dänzer            if (hole->offset == (va + size)) {
330206d07625c9fd69c7d00a8722bd7390c5215bfe2Michel Dänzer                hole->offset = va;
331206d07625c9fd69c7d00a8722bd7390c5215bfe2Michel Dänzer                hole->size += size;
332206d07625c9fd69c7d00a8722bd7390c5215bfe2Michel Dänzer                /* Merge lower hole if it's adjacent */
333206d07625c9fd69c7d00a8722bd7390c5215bfe2Michel Dänzer                if (next != hole && &next->list != &mgr->va_holes &&
334206d07625c9fd69c7d00a8722bd7390c5215bfe2Michel Dänzer                    (next->offset + next->size) == va) {
335206d07625c9fd69c7d00a8722bd7390c5215bfe2Michel Dänzer                    next->size += hole->size;
336206d07625c9fd69c7d00a8722bd7390c5215bfe2Michel Dänzer                    list_del(&hole->list);
337206d07625c9fd69c7d00a8722bd7390c5215bfe2Michel Dänzer                    FREE(hole);
338206d07625c9fd69c7d00a8722bd7390c5215bfe2Michel Dänzer                }
339206d07625c9fd69c7d00a8722bd7390c5215bfe2Michel Dänzer                goto out;
340206d07625c9fd69c7d00a8722bd7390c5215bfe2Michel Dänzer            }
341206d07625c9fd69c7d00a8722bd7390c5215bfe2Michel Dänzer        }
342206d07625c9fd69c7d00a8722bd7390c5215bfe2Michel Dänzer
343206d07625c9fd69c7d00a8722bd7390c5215bfe2Michel Dänzer        /* Grow lower hole if it's adjacent */
344206d07625c9fd69c7d00a8722bd7390c5215bfe2Michel Dänzer        if (next != hole && &next->list != &mgr->va_holes &&
345206d07625c9fd69c7d00a8722bd7390c5215bfe2Michel Dänzer            (next->offset + next->size) == va) {
346206d07625c9fd69c7d00a8722bd7390c5215bfe2Michel Dänzer            next->size += size;
347206d07625c9fd69c7d00a8722bd7390c5215bfe2Michel Dänzer            goto out;
348206d07625c9fd69c7d00a8722bd7390c5215bfe2Michel Dänzer        }
349bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
350bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse        /* FIXME on allocation failure we just lose virtual address space
351bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse         * maybe print a warning
352bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse         */
353206d07625c9fd69c7d00a8722bd7390c5215bfe2Michel Dänzer        next = CALLOC_STRUCT(radeon_bo_va_hole);
354206d07625c9fd69c7d00a8722bd7390c5215bfe2Michel Dänzer        if (next) {
355206d07625c9fd69c7d00a8722bd7390c5215bfe2Michel Dänzer            next->size = size;
356206d07625c9fd69c7d00a8722bd7390c5215bfe2Michel Dänzer            next->offset = va;
357206d07625c9fd69c7d00a8722bd7390c5215bfe2Michel Dänzer            list_add(&next->list, &hole->list);
358bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse        }
359bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    }
360206d07625c9fd69c7d00a8722bd7390c5215bfe2Michel Dänzerout:
361bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    pipe_mutex_unlock(mgr->bo_va_mutex);
362bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse}
363bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
3646ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšákstatic void radeon_bo_destroy(struct pb_buffer *_buf)
3656ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák{
3666ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    struct radeon_bo *bo = radeon_bo(_buf);
367bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    struct radeon_bomgr *mgr = bo->mgr;
3683da5196263fb2ae60483044cbd34c94270e2accdBrian Paul    struct drm_gem_close args;
3693da5196263fb2ae60483044cbd34c94270e2accdBrian Paul
3703da5196263fb2ae60483044cbd34c94270e2accdBrian Paul    memset(&args, 0, sizeof(args));
371c35572352e3e92683988ee8d151b47f4190d62f9Marek Olšák
372c35572352e3e92683988ee8d151b47f4190d62f9Marek Olšák    if (bo->name) {
373c35572352e3e92683988ee8d151b47f4190d62f9Marek Olšák        pipe_mutex_lock(bo->mgr->bo_handles_mutex);
374c35572352e3e92683988ee8d151b47f4190d62f9Marek Olšák        util_hash_table_remove(bo->mgr->bo_handles,
375bbc320a94def6178028a4c46012c737839e1cf61Jerome Glisse                               (void*)(uintptr_t)bo->name);
376c35572352e3e92683988ee8d151b47f4190d62f9Marek Olšák        pipe_mutex_unlock(bo->mgr->bo_handles_mutex);
377c35572352e3e92683988ee8d151b47f4190d62f9Marek Olšák    }
3786ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
379c35572352e3e92683988ee8d151b47f4190d62f9Marek Olšák    if (bo->ptr)
380a3cd2c6c9b3724dbc3aa565dab98968c46bde963Marek Olšák        os_munmap(bo->ptr, bo->base.size);
381c35572352e3e92683988ee8d151b47f4190d62f9Marek Olšák
3828c44e5a144009a03c20befa6468d19d41c802795Christian König    /* Close object. */
3838c44e5a144009a03c20befa6468d19d41c802795Christian König    args.handle = bo->handle;
3848c44e5a144009a03c20befa6468d19d41c802795Christian König    drmIoctl(bo->rws->fd, DRM_IOCTL_GEM_CLOSE, &args);
3858c44e5a144009a03c20befa6468d19d41c802795Christian König
386bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    if (mgr->va) {
387bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse        radeon_bomgr_free_va(mgr, bo->va, bo->va_size);
388bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    }
389bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
390c35572352e3e92683988ee8d151b47f4190d62f9Marek Olšák    pipe_mutex_destroy(bo->map_mutex);
391c35572352e3e92683988ee8d151b47f4190d62f9Marek Olšák    FREE(bo);
3926ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák}
3936ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
3940a6120244e66494db070ce875c0a464fbc5b15a1Marek Olšákstatic void *radeon_bo_map(struct radeon_winsys_cs_handle *buf,
3950a6120244e66494db070ce875c0a464fbc5b15a1Marek Olšák                           struct radeon_winsys_cs *rcs,
3960a6120244e66494db070ce875c0a464fbc5b15a1Marek Olšák                           enum pipe_transfer_usage usage)
3976ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák{
3980a6120244e66494db070ce875c0a464fbc5b15a1Marek Olšák    struct radeon_bo *bo = (struct radeon_bo*)buf;
3990a6120244e66494db070ce875c0a464fbc5b15a1Marek Olšák    struct radeon_drm_cs *cs = (struct radeon_drm_cs*)rcs;
4000a6120244e66494db070ce875c0a464fbc5b15a1Marek Olšák    struct drm_radeon_gem_mmap args = {0};
4018decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák    void *ptr;
4026ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
4036ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    /* If it's not unsynchronized bo_map, flush CS if needed and then wait. */
4040a6120244e66494db070ce875c0a464fbc5b15a1Marek Olšák    if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) {
40545e1cd522bd26a5aa3d424ea49975b90feef8450Marek Olšák        /* DONTBLOCK doesn't make sense with UNSYNCHRONIZED. */
4060a6120244e66494db070ce875c0a464fbc5b15a1Marek Olšák        if (usage & PIPE_TRANSFER_DONTBLOCK) {
4070a6120244e66494db070ce875c0a464fbc5b15a1Marek Olšák            if (!(usage & PIPE_TRANSFER_WRITE)) {
408ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák                /* Mapping for read.
409ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák                 *
410ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák                 * Since we are mapping for read, we don't need to wait
411ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák                 * if the GPU is using the buffer for read too
412ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák                 * (neither one is changing it).
413ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák                 *
414ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák                 * Only check whether the buffer is being used for write. */
415ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák                if (radeon_bo_is_referenced_by_cs_for_write(cs, bo)) {
416ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák                    cs->flush_cs(cs->flush_data, RADEON_FLUSH_ASYNC);
417ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák                    return NULL;
418ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák                }
41945e1cd522bd26a5aa3d424ea49975b90feef8450Marek Olšák
420ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák                if (radeon_bo_is_busy((struct pb_buffer*)bo,
421ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák                                      RADEON_USAGE_WRITE)) {
422ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák                    return NULL;
423ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák                }
424ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák            } else {
425ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák                if (radeon_bo_is_referenced_by_cs(cs, bo)) {
426ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák                    cs->flush_cs(cs->flush_data, RADEON_FLUSH_ASYNC);
427ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák                    return NULL;
428ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák                }
429ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák
430ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák                if (radeon_bo_is_busy((struct pb_buffer*)bo,
431ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák                                      RADEON_USAGE_READWRITE)) {
432ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák                    return NULL;
433ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák                }
43445e1cd522bd26a5aa3d424ea49975b90feef8450Marek Olšák            }
43545e1cd522bd26a5aa3d424ea49975b90feef8450Marek Olšák        } else {
4360a6120244e66494db070ce875c0a464fbc5b15a1Marek Olšák            if (!(usage & PIPE_TRANSFER_WRITE)) {
4376caac3ecb8bc32d92c35fdb1f0a67541ffa8af29Marek Olšák                /* Mapping for read.
4386caac3ecb8bc32d92c35fdb1f0a67541ffa8af29Marek Olšák                 *
4396caac3ecb8bc32d92c35fdb1f0a67541ffa8af29Marek Olšák                 * Since we are mapping for read, we don't need to wait
4406caac3ecb8bc32d92c35fdb1f0a67541ffa8af29Marek Olšák                 * if the GPU is using the buffer for read too
4416caac3ecb8bc32d92c35fdb1f0a67541ffa8af29Marek Olšák                 * (neither one is changing it).
4426caac3ecb8bc32d92c35fdb1f0a67541ffa8af29Marek Olšák                 *
4436caac3ecb8bc32d92c35fdb1f0a67541ffa8af29Marek Olšák                 * Only check whether the buffer is being used for write. */
4446caac3ecb8bc32d92c35fdb1f0a67541ffa8af29Marek Olšák                if (radeon_bo_is_referenced_by_cs_for_write(cs, bo)) {
4456caac3ecb8bc32d92c35fdb1f0a67541ffa8af29Marek Olšák                    cs->flush_cs(cs->flush_data, 0);
4461554e69e00566bc7255b82f5ea93b1f02f1a5bb3Marek Olšák                }
447ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák                radeon_bo_wait((struct pb_buffer*)bo,
448ebfcc58b93cc08c534857c2314694e35b29690aeMarek Olšák                               RADEON_USAGE_WRITE);
4495650a719f0c69c00954e47bd7a7b3e9433cb551dMarek Olšák            } else {
4506caac3ecb8bc32d92c35fdb1f0a67541ffa8af29Marek Olšák                /* Mapping for write. */
4516caac3ecb8bc32d92c35fdb1f0a67541ffa8af29Marek Olšák                if (radeon_bo_is_referenced_by_cs(cs, bo)) {
4526caac3ecb8bc32d92c35fdb1f0a67541ffa8af29Marek Olšák                    cs->flush_cs(cs->flush_data, 0);
4536caac3ecb8bc32d92c35fdb1f0a67541ffa8af29Marek Olšák                } else {
4546caac3ecb8bc32d92c35fdb1f0a67541ffa8af29Marek Olšák                    /* Try to avoid busy-waiting in radeon_bo_wait. */
4556caac3ecb8bc32d92c35fdb1f0a67541ffa8af29Marek Olšák                    if (p_atomic_read(&bo->num_active_ioctls))
4566caac3ecb8bc32d92c35fdb1f0a67541ffa8af29Marek Olšák                        radeon_drm_cs_sync_flush(cs);
4576caac3ecb8bc32d92c35fdb1f0a67541ffa8af29Marek Olšák                }
4586caac3ecb8bc32d92c35fdb1f0a67541ffa8af29Marek Olšák
4591e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák                radeon_bo_wait((struct pb_buffer*)bo, RADEON_USAGE_READWRITE);
46045e1cd522bd26a5aa3d424ea49975b90feef8450Marek Olšák            }
4616ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák        }
4626ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    }
4636ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
4648decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák    /* Return the pointer if it's already mapped. */
4658decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák    if (bo->ptr)
4668decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák        return bo->ptr;
4678decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák
4688decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák    /* Map the buffer. */
4698decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák    pipe_mutex_lock(bo->map_mutex);
470652bf121f2124ec92b74f6e3e40e6aefcc1c50dcMarek Olšák    /* Return the pointer if it's already mapped (in case of a race). */
471652bf121f2124ec92b74f6e3e40e6aefcc1c50dcMarek Olšák    if (bo->ptr) {
472652bf121f2124ec92b74f6e3e40e6aefcc1c50dcMarek Olšák        pipe_mutex_unlock(bo->map_mutex);
473652bf121f2124ec92b74f6e3e40e6aefcc1c50dcMarek Olšák        return bo->ptr;
474652bf121f2124ec92b74f6e3e40e6aefcc1c50dcMarek Olšák    }
4758decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák    args.handle = bo->handle;
4768decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák    args.offset = 0;
477a3cd2c6c9b3724dbc3aa565dab98968c46bde963Marek Olšák    args.size = (uint64_t)bo->base.size;
4788decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák    if (drmCommandWriteRead(bo->rws->fd,
4798decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák                            DRM_RADEON_GEM_MMAP,
4808decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák                            &args,
4818decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák                            sizeof(args))) {
4828decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák        pipe_mutex_unlock(bo->map_mutex);
4838decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák        fprintf(stderr, "radeon: gem_mmap failed: %p 0x%08X\n",
4848decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák                bo, bo->handle);
4858decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák        return NULL;
4868decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák    }
4878decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák
48870b1837dfb1b282ad9efcaeec4f9c8da5f9a74d8Chia-I Wu    ptr = os_mmap(0, args.size, PROT_READ|PROT_WRITE, MAP_SHARED,
4898decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák               bo->rws->fd, args.addr_ptr);
4908decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák    if (ptr == MAP_FAILED) {
4918decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák        pipe_mutex_unlock(bo->map_mutex);
4928decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák        fprintf(stderr, "radeon: mmap failed, errno: %i\n", errno);
4938decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák        return NULL;
4946ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    }
4958decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák    bo->ptr = ptr;
4968decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák    pipe_mutex_unlock(bo->map_mutex);
4976ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
4986ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    return bo->ptr;
4996ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák}
5006ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
5010a6120244e66494db070ce875c0a464fbc5b15a1Marek Olšákstatic void radeon_bo_unmap(struct radeon_winsys_cs_handle *_buf)
5026ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák{
5036ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    /* NOP */
5046ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák}
5056ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
5066ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšákstatic void radeon_bo_get_base_buffer(struct pb_buffer *buf,
507bbc320a94def6178028a4c46012c737839e1cf61Jerome Glisse                                      struct pb_buffer **base_buf,
508bbc320a94def6178028a4c46012c737839e1cf61Jerome Glisse                                      unsigned *offset)
5096ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák{
5106ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    *base_buf = buf;
5116ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    *offset = 0;
5126ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák}
5136ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
5146ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšákstatic enum pipe_error radeon_bo_validate(struct pb_buffer *_buf,
515bbc320a94def6178028a4c46012c737839e1cf61Jerome Glisse                                          struct pb_validate *vl,
516bbc320a94def6178028a4c46012c737839e1cf61Jerome Glisse                                          unsigned flags)
5176ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák{
5186ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    /* Always pinned */
5196ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    return PIPE_OK;
5206ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák}
5216ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
5226ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšákstatic void radeon_bo_fence(struct pb_buffer *buf,
5236ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák                            struct pipe_fence_handle *fence)
5246ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák{
5256ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák}
5266ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
5276ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšákconst struct pb_vtbl radeon_bo_vtbl = {
5286ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    radeon_bo_destroy,
5290a6120244e66494db070ce875c0a464fbc5b15a1Marek Olšák    NULL, /* never called */
5300a6120244e66494db070ce875c0a464fbc5b15a1Marek Olšák    NULL, /* never called */
5316ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    radeon_bo_validate,
5326ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    radeon_bo_fence,
5336ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    radeon_bo_get_base_buffer,
5346ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák};
5356ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
5366ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšákstatic struct pb_buffer *radeon_bomgr_create_bo(struct pb_manager *_mgr,
537bbc320a94def6178028a4c46012c737839e1cf61Jerome Glisse                                                pb_size size,
538bbc320a94def6178028a4c46012c737839e1cf61Jerome Glisse                                                const struct pb_desc *desc)
5396ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák{
5406ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    struct radeon_bomgr *mgr = radeon_bomgr(_mgr);
5416ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    struct radeon_drm_winsys *rws = mgr->rws;
5426ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    struct radeon_bo *bo;
5433da5196263fb2ae60483044cbd34c94270e2accdBrian Paul    struct drm_radeon_gem_create args;
544bfa51dfeac67a7e3383614374c86bdfb5751997aMarek Olšák    struct radeon_bo_desc *rdesc = (struct radeon_bo_desc*)desc;
545bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    int r;
5466ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
5473da5196263fb2ae60483044cbd34c94270e2accdBrian Paul    memset(&args, 0, sizeof(args));
5483da5196263fb2ae60483044cbd34c94270e2accdBrian Paul
54993f4e3cb6c1ca303ee1f5c2a2491a8eff33f2633Marek Olšák    assert(rdesc->initial_domains);
550363ff844753c46ac9c13866627e096b091ea81f8Marek Olšák    assert((rdesc->initial_domains &
551363ff844753c46ac9c13866627e096b091ea81f8Marek Olšák            ~(RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM)) == 0);
552363ff844753c46ac9c13866627e096b091ea81f8Marek Olšák
5536ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    args.size = size;
5546ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    args.alignment = desc->alignment;
555bfa51dfeac67a7e3383614374c86bdfb5751997aMarek Olšák    args.initial_domain = rdesc->initial_domains;
5566ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
5576ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    if (drmCommandWriteRead(rws->fd, DRM_RADEON_GEM_CREATE,
5586ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák                            &args, sizeof(args))) {
5599d5de0fcb6ced7a4da85a09ad25dcbc2b21bfdf9Marek Olšák        fprintf(stderr, "radeon: Failed to allocate a buffer:\n");
5609d5de0fcb6ced7a4da85a09ad25dcbc2b21bfdf9Marek Olšák        fprintf(stderr, "radeon:    size      : %d bytes\n", size);
5619d5de0fcb6ced7a4da85a09ad25dcbc2b21bfdf9Marek Olšák        fprintf(stderr, "radeon:    alignment : %d bytes\n", desc->alignment);
5629d5de0fcb6ced7a4da85a09ad25dcbc2b21bfdf9Marek Olšák        fprintf(stderr, "radeon:    domains   : %d\n", args.initial_domain);
5636ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák        return NULL;
5646ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    }
5656ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
5666ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    bo = CALLOC_STRUCT(radeon_bo);
5676ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    if (!bo)
568bbc320a94def6178028a4c46012c737839e1cf61Jerome Glisse        return NULL;
5696ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
5704682e706012fe26627a2f827db01b5068cc62814Marek Olšák    pipe_reference_init(&bo->base.reference, 1);
5714682e706012fe26627a2f827db01b5068cc62814Marek Olšák    bo->base.alignment = desc->alignment;
5724682e706012fe26627a2f827db01b5068cc62814Marek Olšák    bo->base.usage = desc->usage;
5734682e706012fe26627a2f827db01b5068cc62814Marek Olšák    bo->base.size = size;
5746ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    bo->base.vtbl = &radeon_bo_vtbl;
5756ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    bo->mgr = mgr;
576df54b53b7d12a3bca5867b6649cb308feb36f0daMarek Olšák    bo->rws = mgr->rws;
5776ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    bo->handle = args.handle;
578bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    bo->va = 0;
5798decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák    pipe_mutex_init(bo->map_mutex);
5806ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
581bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    if (mgr->va) {
582bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse        struct drm_radeon_gem_va va;
583bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
584bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse        bo->va_size = align(size,  4096);
585356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse        bo->va = radeon_bomgr_find_va(mgr, bo->va_size, desc->alignment);
586bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
587bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse        va.handle = bo->handle;
588bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse        va.vm_id = 0;
589bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse        va.operation = RADEON_VA_MAP;
590bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse        va.flags = RADEON_VM_PAGE_READABLE |
591bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse                   RADEON_VM_PAGE_WRITEABLE |
592bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse                   RADEON_VM_PAGE_SNOOPED;
593bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse        va.offset = bo->va;
594bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse        r = drmCommandWriteRead(rws->fd, DRM_RADEON_GEM_VA, &va, sizeof(va));
595bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse        if (r && va.operation == RADEON_VA_RESULT_ERROR) {
596bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse            fprintf(stderr, "radeon: Failed to allocate a buffer:\n");
597bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse            fprintf(stderr, "radeon:    size      : %d bytes\n", size);
598bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse            fprintf(stderr, "radeon:    alignment : %d bytes\n", desc->alignment);
599bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse            fprintf(stderr, "radeon:    domains   : %d\n", args.initial_domain);
600bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse            radeon_bo_destroy(&bo->base);
601bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse            return NULL;
602bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse        }
603bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse        if (va.operation == RADEON_VA_RESULT_VA_EXIST) {
604bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse            radeon_bomgr_free_va(mgr, bo->va, bo->va_size);
605bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse            bo->va = va.offset;
606bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse            radeon_bomgr_force_va(mgr, bo->va, bo->va_size);
607bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse        }
608bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    }
609bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
6106ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    return &bo->base;
6116ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák}
6126ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
6136ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšákstatic void radeon_bomgr_flush(struct pb_manager *mgr)
6146ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák{
6156ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    /* NOP */
6166ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák}
6176ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
618a87730ff3f83253465fbe9a1e9e9b1ea92cb79b9Marek Olšák/* This is for the cache bufmgr. */
619a87730ff3f83253465fbe9a1e9e9b1ea92cb79b9Marek Olšákstatic boolean radeon_bomgr_is_buffer_busy(struct pb_manager *_mgr,
620a87730ff3f83253465fbe9a1e9e9b1ea92cb79b9Marek Olšák                                           struct pb_buffer *_buf)
621a87730ff3f83253465fbe9a1e9e9b1ea92cb79b9Marek Olšák{
622a87730ff3f83253465fbe9a1e9e9b1ea92cb79b9Marek Olšák   struct radeon_bo *bo = radeon_bo(_buf);
623a87730ff3f83253465fbe9a1e9e9b1ea92cb79b9Marek Olšák
624a87730ff3f83253465fbe9a1e9e9b1ea92cb79b9Marek Olšák   if (radeon_bo_is_referenced_by_any_cs(bo)) {
625333d3daf472485b247101932d95ccb798cb55f7bMarek Olšák       return TRUE;
626a87730ff3f83253465fbe9a1e9e9b1ea92cb79b9Marek Olšák   }
627a87730ff3f83253465fbe9a1e9e9b1ea92cb79b9Marek Olšák
6281e3c81a068c4ae04cd1c6b18c687d5be69b7b8c4Marek Olšák   if (radeon_bo_is_busy((struct pb_buffer*)bo, RADEON_USAGE_READWRITE)) {
629333d3daf472485b247101932d95ccb798cb55f7bMarek Olšák       return TRUE;
630a87730ff3f83253465fbe9a1e9e9b1ea92cb79b9Marek Olšák   }
631a87730ff3f83253465fbe9a1e9e9b1ea92cb79b9Marek Olšák
632333d3daf472485b247101932d95ccb798cb55f7bMarek Olšák   return FALSE;
633a87730ff3f83253465fbe9a1e9e9b1ea92cb79b9Marek Olšák}
634a87730ff3f83253465fbe9a1e9e9b1ea92cb79b9Marek Olšák
6356ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšákstatic void radeon_bomgr_destroy(struct pb_manager *_mgr)
6366ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák{
6376ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    struct radeon_bomgr *mgr = radeon_bomgr(_mgr);
6386ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    util_hash_table_destroy(mgr->bo_handles);
6396ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    pipe_mutex_destroy(mgr->bo_handles_mutex);
640bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    pipe_mutex_destroy(mgr->bo_va_mutex);
6416ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    FREE(mgr);
6426ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák}
6436ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
6448ab1fcc66a58ca87fb19fea2b0e14e62562decccMarek Olšák#define PTR_TO_UINT(x) ((unsigned)((intptr_t)(x)))
645685c3262b945a7f0e9f1f3a9409a12fdda08c828Marek Olšák
6466ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšákstatic unsigned handle_hash(void *key)
6476ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák{
648685c3262b945a7f0e9f1f3a9409a12fdda08c828Marek Olšák    return PTR_TO_UINT(key);
6496ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák}
6506ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
6516ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšákstatic int handle_compare(void *key1, void *key2)
6526ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák{
6538ab1fcc66a58ca87fb19fea2b0e14e62562decccMarek Olšák    return PTR_TO_UINT(key1) != PTR_TO_UINT(key2);
6546ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák}
6556ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
6566ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšákstruct pb_manager *radeon_bomgr_create(struct radeon_drm_winsys *rws)
6576ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák{
6586ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    struct radeon_bomgr *mgr;
6596ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
6606ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    mgr = CALLOC_STRUCT(radeon_bomgr);
6616ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    if (!mgr)
662bbc320a94def6178028a4c46012c737839e1cf61Jerome Glisse        return NULL;
6636ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
6646ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    mgr->base.destroy = radeon_bomgr_destroy;
6656ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    mgr->base.create_buffer = radeon_bomgr_create_bo;
6666ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    mgr->base.flush = radeon_bomgr_flush;
667a87730ff3f83253465fbe9a1e9e9b1ea92cb79b9Marek Olšák    mgr->base.is_buffer_busy = radeon_bomgr_is_buffer_busy;
6686ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
6696ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    mgr->rws = rws;
6706ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    mgr->bo_handles = util_hash_table_create(handle_hash, handle_compare);
6716ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    pipe_mutex_init(mgr->bo_handles_mutex);
672bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    pipe_mutex_init(mgr->bo_va_mutex);
673bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
674bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    mgr->va = rws->info.r600_virtual_address;
675bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    mgr->va_offset = rws->info.r600_va_start;
676bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    list_inithead(&mgr->va_holes);
677bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
6786ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    return &mgr->base;
6796ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák}
6806ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
681c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glissestatic unsigned eg_tile_split(unsigned tile_split)
682c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse{
683c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse    switch (tile_split) {
684c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse    case 0:     tile_split = 64;    break;
685c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse    case 1:     tile_split = 128;   break;
686c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse    case 2:     tile_split = 256;   break;
687c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse    case 3:     tile_split = 512;   break;
688c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse    default:
689c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse    case 4:     tile_split = 1024;  break;
690c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse    case 5:     tile_split = 2048;  break;
691c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse    case 6:     tile_split = 4096;  break;
692c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse    }
693c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse    return tile_split;
694c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse}
695c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse
69611f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzerstatic unsigned eg_tile_split_rev(unsigned eg_tile_split)
69711f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer{
69811f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer    switch (eg_tile_split) {
69911f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer    case 64:    return 0;
70011f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer    case 128:   return 1;
70111f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer    case 256:   return 2;
70211f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer    case 512:   return 3;
70311f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer    default:
70411f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer    case 1024:  return 4;
70511f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer    case 2048:  return 5;
70611f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer    case 4096:  return 6;
70711f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer    }
70811f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer}
70911f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer
710d35aeff4bb0b03450b2c3c08bd7f84db5bf43283Marek Olšákstatic void radeon_bo_get_tiling(struct pb_buffer *_buf,
711d35aeff4bb0b03450b2c3c08bd7f84db5bf43283Marek Olšák                                 enum radeon_bo_layout *microtiled,
712c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse                                 enum radeon_bo_layout *macrotiled,
713c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse                                 unsigned *bankw, unsigned *bankh,
714c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse                                 unsigned *tile_split,
715c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse                                 unsigned *stencil_tile_split,
716c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse                                 unsigned *mtilea)
7176ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák{
7182664980760c5cf2e7dde4065f9cc8e8b865627c3Marek Olšák    struct radeon_bo *bo = get_radeon_bo(_buf);
7193da5196263fb2ae60483044cbd34c94270e2accdBrian Paul    struct drm_radeon_gem_set_tiling args;
7203da5196263fb2ae60483044cbd34c94270e2accdBrian Paul
7213da5196263fb2ae60483044cbd34c94270e2accdBrian Paul    memset(&args, 0, sizeof(args));
7226ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
7236ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    args.handle = bo->handle;
7246ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
725df54b53b7d12a3bca5867b6649cb308feb36f0daMarek Olšák    drmCommandWriteRead(bo->rws->fd,
7266ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák                        DRM_RADEON_GEM_GET_TILING,
7276ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák                        &args,
7286ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák                        sizeof(args));
7296ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
730d35aeff4bb0b03450b2c3c08bd7f84db5bf43283Marek Olšák    *microtiled = RADEON_LAYOUT_LINEAR;
731d35aeff4bb0b03450b2c3c08bd7f84db5bf43283Marek Olšák    *macrotiled = RADEON_LAYOUT_LINEAR;
7326ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    if (args.tiling_flags & RADEON_BO_FLAGS_MICRO_TILE)
733bbc320a94def6178028a4c46012c737839e1cf61Jerome Glisse        *microtiled = RADEON_LAYOUT_TILED;
7346ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
7356ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    if (args.tiling_flags & RADEON_BO_FLAGS_MACRO_TILE)
736bbc320a94def6178028a4c46012c737839e1cf61Jerome Glisse        *macrotiled = RADEON_LAYOUT_TILED;
737c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse    if (bankw && tile_split && stencil_tile_split && mtilea && tile_split) {
738c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse        *bankw = (args.tiling_flags >> RADEON_TILING_EG_BANKW_SHIFT) & RADEON_TILING_EG_BANKW_MASK;
739c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse        *bankh = (args.tiling_flags >> RADEON_TILING_EG_BANKH_SHIFT) & RADEON_TILING_EG_BANKH_MASK;
740c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse        *tile_split = (args.tiling_flags >> RADEON_TILING_EG_TILE_SPLIT_SHIFT) & RADEON_TILING_EG_TILE_SPLIT_MASK;
741c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse        *stencil_tile_split = (args.tiling_flags >> RADEON_TILING_EG_STENCIL_TILE_SPLIT_SHIFT) & RADEON_TILING_EG_STENCIL_TILE_SPLIT_MASK;
742c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse        *mtilea = (args.tiling_flags >> RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT) & RADEON_TILING_EG_MACRO_TILE_ASPECT_MASK;
743c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse        *tile_split = eg_tile_split(*tile_split);
744c0c979eebc076b95cc8d18a013ce2968fe6311adJerome Glisse    }
7456ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák}
7466ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
747d35aeff4bb0b03450b2c3c08bd7f84db5bf43283Marek Olšákstatic void radeon_bo_set_tiling(struct pb_buffer *_buf,
7487446a0407d4e61a826385c11ed6c401837baf095Michel Dänzer                                 struct radeon_winsys_cs *rcs,
749d35aeff4bb0b03450b2c3c08bd7f84db5bf43283Marek Olšák                                 enum radeon_bo_layout microtiled,
750d35aeff4bb0b03450b2c3c08bd7f84db5bf43283Marek Olšák                                 enum radeon_bo_layout macrotiled,
75111f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer                                 unsigned bankw, unsigned bankh,
75211f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer                                 unsigned tile_split,
75311f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer                                 unsigned stencil_tile_split,
75411f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer                                 unsigned mtilea,
7556ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák                                 uint32_t pitch)
7566ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák{
7572664980760c5cf2e7dde4065f9cc8e8b865627c3Marek Olšák    struct radeon_bo *bo = get_radeon_bo(_buf);
7587446a0407d4e61a826385c11ed6c401837baf095Michel Dänzer    struct radeon_drm_cs *cs = radeon_drm_cs(rcs);
7593da5196263fb2ae60483044cbd34c94270e2accdBrian Paul    struct drm_radeon_gem_set_tiling args;
7603da5196263fb2ae60483044cbd34c94270e2accdBrian Paul
7613da5196263fb2ae60483044cbd34c94270e2accdBrian Paul    memset(&args, 0, sizeof(args));
7626ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
7637446a0407d4e61a826385c11ed6c401837baf095Michel Dänzer    /* Tiling determines how DRM treats the buffer data.
7647446a0407d4e61a826385c11ed6c401837baf095Michel Dänzer     * We must flush CS when changing it if the buffer is referenced. */
7657446a0407d4e61a826385c11ed6c401837baf095Michel Dänzer    if (cs && radeon_bo_is_referenced_by_cs(cs, bo)) {
7667446a0407d4e61a826385c11ed6c401837baf095Michel Dänzer        cs->flush_cs(cs->flush_data, 0);
7677446a0407d4e61a826385c11ed6c401837baf095Michel Dänzer    }
7687446a0407d4e61a826385c11ed6c401837baf095Michel Dänzer
769fa3f1348e49feeac511dbe5b22bbddc47f56ba81Marek Olšák    while (p_atomic_read(&bo->num_active_ioctls)) {
770fa3f1348e49feeac511dbe5b22bbddc47f56ba81Marek Olšák        sched_yield();
771fa3f1348e49feeac511dbe5b22bbddc47f56ba81Marek Olšák    }
772fa3f1348e49feeac511dbe5b22bbddc47f56ba81Marek Olšák
773d35aeff4bb0b03450b2c3c08bd7f84db5bf43283Marek Olšák    if (microtiled == RADEON_LAYOUT_TILED)
7746ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák        args.tiling_flags |= RADEON_BO_FLAGS_MICRO_TILE;
775d35aeff4bb0b03450b2c3c08bd7f84db5bf43283Marek Olšák    else if (microtiled == RADEON_LAYOUT_SQUARETILED)
7766ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák        args.tiling_flags |= RADEON_BO_FLAGS_MICRO_TILE_SQUARE;
7776ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
778d35aeff4bb0b03450b2c3c08bd7f84db5bf43283Marek Olšák    if (macrotiled == RADEON_LAYOUT_TILED)
7796ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák        args.tiling_flags |= RADEON_BO_FLAGS_MACRO_TILE;
7806ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
78111f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer    args.tiling_flags |= (bankw & RADEON_TILING_EG_BANKW_MASK) <<
78211f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer        RADEON_TILING_EG_BANKW_SHIFT;
78311f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer    args.tiling_flags |= (bankh & RADEON_TILING_EG_BANKH_MASK) <<
78411f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer        RADEON_TILING_EG_BANKH_SHIFT;
7857446a0407d4e61a826385c11ed6c401837baf095Michel Dänzer    if (tile_split) {
7867446a0407d4e61a826385c11ed6c401837baf095Michel Dänzer	args.tiling_flags |= (eg_tile_split_rev(tile_split) &
7877446a0407d4e61a826385c11ed6c401837baf095Michel Dänzer			      RADEON_TILING_EG_TILE_SPLIT_MASK) <<
7887446a0407d4e61a826385c11ed6c401837baf095Michel Dänzer	    RADEON_TILING_EG_TILE_SPLIT_SHIFT;
7897446a0407d4e61a826385c11ed6c401837baf095Michel Dänzer    }
79011f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer    args.tiling_flags |= (stencil_tile_split &
79111f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer			  RADEON_TILING_EG_STENCIL_TILE_SPLIT_MASK) <<
79211f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer        RADEON_TILING_EG_STENCIL_TILE_SPLIT_SHIFT;
79311f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer    args.tiling_flags |= (mtilea & RADEON_TILING_EG_MACRO_TILE_ASPECT_MASK) <<
79411f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer        RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT;
79511f056a3f0b87e86267efa8b5ac9d36a343c9dc1Michel Dänzer
7966ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    args.handle = bo->handle;
7976ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    args.pitch = pitch;
7986ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
799df54b53b7d12a3bca5867b6649cb308feb36f0daMarek Olšák    drmCommandWriteRead(bo->rws->fd,
8006ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák                        DRM_RADEON_GEM_SET_TILING,
8016ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák                        &args,
8026ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák                        sizeof(args));
8036ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák}
8046ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
805d35aeff4bb0b03450b2c3c08bd7f84db5bf43283Marek Olšákstatic struct radeon_winsys_cs_handle *radeon_drm_get_cs_handle(
806d35aeff4bb0b03450b2c3c08bd7f84db5bf43283Marek Olšák        struct pb_buffer *_buf)
8076ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák{
8086ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    /* return radeon_bo. */
8092664980760c5cf2e7dde4065f9cc8e8b865627c3Marek Olšák    return (struct radeon_winsys_cs_handle*)get_radeon_bo(_buf);
8106ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák}
8116ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
812d35aeff4bb0b03450b2c3c08bd7f84db5bf43283Marek Olšákstatic struct pb_buffer *
813d35aeff4bb0b03450b2c3c08bd7f84db5bf43283Marek Olšákradeon_winsys_bo_create(struct radeon_winsys *rws,
8146ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák                        unsigned size,
8156ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák                        unsigned alignment,
81693f4e3cb6c1ca303ee1f5c2a2491a8eff33f2633Marek Olšák                        unsigned bind,
81793f4e3cb6c1ca303ee1f5c2a2491a8eff33f2633Marek Olšák                        enum radeon_bo_domain domain)
8186ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák{
8196ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    struct radeon_drm_winsys *ws = radeon_drm_winsys(rws);
820bfa51dfeac67a7e3383614374c86bdfb5751997aMarek Olšák    struct radeon_bo_desc desc;
8216ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    struct pb_manager *provider;
8226ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    struct pb_buffer *buffer;
8236ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
8246ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    memset(&desc, 0, sizeof(desc));
825bfa51dfeac67a7e3383614374c86bdfb5751997aMarek Olšák    desc.base.alignment = alignment;
826363ff844753c46ac9c13866627e096b091ea81f8Marek Olšák
827363ff844753c46ac9c13866627e096b091ea81f8Marek Olšák    /* Additional criteria for the cache manager. */
82893f4e3cb6c1ca303ee1f5c2a2491a8eff33f2633Marek Olšák    desc.base.usage = domain;
82993f4e3cb6c1ca303ee1f5c2a2491a8eff33f2633Marek Olšák    desc.initial_domains = domain;
8306ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
8316ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    /* Assign a buffer manager. */
832533e2289235c61eff9a14bb24da7c8a1ff0b0afaMarek Olšák    if (bind & (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER |
83334f4bd81906d8385eb3e9af721d50e985cb9d7d4Marek Olšák                PIPE_BIND_CONSTANT_BUFFER | PIPE_BIND_CUSTOM))
834bbc320a94def6178028a4c46012c737839e1cf61Jerome Glisse        provider = ws->cman;
8356ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    else
8366ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák        provider = ws->kman;
8376ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
838bfa51dfeac67a7e3383614374c86bdfb5751997aMarek Olšák    buffer = provider->create_buffer(provider, size, &desc.base);
8396ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    if (!buffer)
840bbc320a94def6178028a4c46012c737839e1cf61Jerome Glisse        return NULL;
8416ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
842d35aeff4bb0b03450b2c3c08bd7f84db5bf43283Marek Olšák    return (struct pb_buffer*)buffer;
8436ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák}
8446ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
845d35aeff4bb0b03450b2c3c08bd7f84db5bf43283Marek Olšákstatic struct pb_buffer *radeon_winsys_bo_from_handle(struct radeon_winsys *rws,
846af8eb5c851a9d566059ae9e37745614cd96b9a13Marek Olšák                                                      struct winsys_handle *whandle,
847af8eb5c851a9d566059ae9e37745614cd96b9a13Marek Olšák                                                      unsigned *stride)
8486ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák{
8496ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    struct radeon_drm_winsys *ws = radeon_drm_winsys(rws);
8506ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    struct radeon_bo *bo;
8516ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    struct radeon_bomgr *mgr = radeon_bomgr(ws->kman);
8526ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    struct drm_gem_open open_arg = {};
853bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    int r;
8546ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
8553da5196263fb2ae60483044cbd34c94270e2accdBrian Paul    memset(&open_arg, 0, sizeof(open_arg));
8563da5196263fb2ae60483044cbd34c94270e2accdBrian Paul
8576ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    /* We must maintain a list of pairs <handle, bo>, so that we always return
8586ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák     * the same BO for one particular handle. If we didn't do that and created
8596ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák     * more than one BO for the same handle and then relocated them in a CS,
8606ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák     * we would hit a deadlock in the kernel.
8616ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák     *
8626ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák     * The list of pairs is guarded by a mutex, of course. */
8636ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    pipe_mutex_lock(mgr->bo_handles_mutex);
8646ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
8656ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    /* First check if there already is an existing bo for the handle. */
8666ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    bo = util_hash_table_get(mgr->bo_handles, (void*)(uintptr_t)whandle->handle);
8676ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    if (bo) {
8686ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák        /* Increase the refcount. */
8696ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák        struct pb_buffer *b = NULL;
8706ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák        pb_reference(&b, &bo->base);
8716ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák        goto done;
8726ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    }
8736ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
8746ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    /* There isn't, create a new one. */
8756ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    bo = CALLOC_STRUCT(radeon_bo);
8766ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    if (!bo) {
8776ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák        goto fail;
8786ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    }
8796ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
8806ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    /* Open the BO. */
8816ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    open_arg.name = whandle->handle;
8826ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    if (drmIoctl(ws->fd, DRM_IOCTL_GEM_OPEN, &open_arg)) {
883032b162ce88ef6ec8ad981fff709eb177d794589Marek Olšák        FREE(bo);
8846ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák        goto fail;
8856ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    }
8866ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    bo->handle = open_arg.handle;
8876ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    bo->name = whandle->handle;
8886ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
8896ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    /* Initialize it. */
8904682e706012fe26627a2f827db01b5068cc62814Marek Olšák    pipe_reference_init(&bo->base.reference, 1);
8914682e706012fe26627a2f827db01b5068cc62814Marek Olšák    bo->base.alignment = 0;
8924682e706012fe26627a2f827db01b5068cc62814Marek Olšák    bo->base.usage = PB_USAGE_GPU_WRITE | PB_USAGE_GPU_READ;
893a3cd2c6c9b3724dbc3aa565dab98968c46bde963Marek Olšák    bo->base.size = open_arg.size;
8946ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    bo->base.vtbl = &radeon_bo_vtbl;
8956ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    bo->mgr = mgr;
896df54b53b7d12a3bca5867b6649cb308feb36f0daMarek Olšák    bo->rws = mgr->rws;
897bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    bo->va = 0;
8988decb0a96de0accfc8361890cbcf9db89f8fe8baMarek Olšák    pipe_mutex_init(bo->map_mutex);
8996ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
9006ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    util_hash_table_set(mgr->bo_handles, (void*)(uintptr_t)whandle->handle, bo);
9016ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
9026ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšákdone:
9036ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    pipe_mutex_unlock(mgr->bo_handles_mutex);
9046ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
9056ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    if (stride)
9066ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák        *stride = whandle->stride;
9076ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
90818abc270c56d5debc02a196634583a25074b3fefMichel Dänzer    if (mgr->va && !bo->va) {
909bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse        struct drm_radeon_gem_va va;
910bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
911bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse        bo->va_size = ((bo->base.size + 4095) & ~4095);
912356eb0aadbb977b0732da077ad31cd66d1b53e23Jerome Glisse        bo->va = radeon_bomgr_find_va(mgr, bo->va_size, 1 << 20);
913bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
914bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse        va.handle = bo->handle;
915bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse        va.operation = RADEON_VA_MAP;
916bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse        va.vm_id = 0;
917bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse        va.offset = bo->va;
918bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse        va.flags = RADEON_VM_PAGE_READABLE |
919bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse                   RADEON_VM_PAGE_WRITEABLE |
920bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse                   RADEON_VM_PAGE_SNOOPED;
921bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse        va.offset = bo->va;
922bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse        r = drmCommandWriteRead(ws->fd, DRM_RADEON_GEM_VA, &va, sizeof(va));
923bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse        if (r && va.operation == RADEON_VA_RESULT_ERROR) {
924bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse            fprintf(stderr, "radeon: Failed to assign virtual address space\n");
925bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse            radeon_bo_destroy(&bo->base);
926bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse            return NULL;
927bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse        }
928bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse        if (va.operation == RADEON_VA_RESULT_VA_EXIST) {
929bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse            radeon_bomgr_free_va(mgr, bo->va, bo->va_size);
930bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse            bo->va = va.offset;
931bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse            radeon_bomgr_force_va(mgr, bo->va, bo->va_size);
932bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse        }
933bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    }
934bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
935d35aeff4bb0b03450b2c3c08bd7f84db5bf43283Marek Olšák    return (struct pb_buffer*)bo;
9366ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
9376ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšákfail:
9386ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    pipe_mutex_unlock(mgr->bo_handles_mutex);
9396ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    return NULL;
9406ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák}
9416ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
942d35aeff4bb0b03450b2c3c08bd7f84db5bf43283Marek Olšákstatic boolean radeon_winsys_bo_get_handle(struct pb_buffer *buffer,
9436ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák                                           unsigned stride,
9446ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák                                           struct winsys_handle *whandle)
9456ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák{
9463da5196263fb2ae60483044cbd34c94270e2accdBrian Paul    struct drm_gem_flink flink;
9472664980760c5cf2e7dde4065f9cc8e8b865627c3Marek Olšák    struct radeon_bo *bo = get_radeon_bo(buffer);
9486ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
9493da5196263fb2ae60483044cbd34c94270e2accdBrian Paul    memset(&flink, 0, sizeof(flink));
9503da5196263fb2ae60483044cbd34c94270e2accdBrian Paul
9516ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) {
9526ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák        if (!bo->flinked) {
9536ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák            flink.handle = bo->handle;
9546ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
955df54b53b7d12a3bca5867b6649cb308feb36f0daMarek Olšák            if (ioctl(bo->rws->fd, DRM_IOCTL_GEM_FLINK, &flink)) {
9566ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák                return FALSE;
9576ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák            }
9586ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
9596ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák            bo->flinked = TRUE;
9606ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák            bo->flink = flink.name;
9616ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák        }
9626ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák        whandle->handle = bo->flink;
9636ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    } else if (whandle->type == DRM_API_HANDLE_TYPE_KMS) {
9646ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák        whandle->handle = bo->handle;
9656ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    }
966df54b53b7d12a3bca5867b6649cb308feb36f0daMarek Olšák
967df54b53b7d12a3bca5867b6649cb308feb36f0daMarek Olšák    whandle->stride = stride;
9686ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    return TRUE;
9696ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák}
9706ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
971669d8766ff3403938794eb80d7769347b6e52174Marek Olšákstatic uint64_t radeon_winsys_bo_va(struct radeon_winsys_cs_handle *buf)
972bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse{
973669d8766ff3403938794eb80d7769347b6e52174Marek Olšák    return ((struct radeon_bo*)buf)->va;
974bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse}
975bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
9766ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšákvoid radeon_bomgr_init_functions(struct radeon_drm_winsys *ws)
9776ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák{
9786ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    ws->base.buffer_get_cs_handle = radeon_drm_get_cs_handle;
9796ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    ws->base.buffer_set_tiling = radeon_bo_set_tiling;
9806ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    ws->base.buffer_get_tiling = radeon_bo_get_tiling;
9816ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    ws->base.buffer_map = radeon_bo_map;
9820a6120244e66494db070ce875c0a464fbc5b15a1Marek Olšák    ws->base.buffer_unmap = radeon_bo_unmap;
9836ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    ws->base.buffer_wait = radeon_bo_wait;
9846ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    ws->base.buffer_is_busy = radeon_bo_is_busy;
9856ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    ws->base.buffer_create = radeon_winsys_bo_create;
9866ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    ws->base.buffer_from_handle = radeon_winsys_bo_from_handle;
9876ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    ws->base.buffer_get_handle = radeon_winsys_bo_get_handle;
988bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    ws->base.buffer_get_virtual_address = radeon_winsys_bo_va;
9896ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák}
990