11f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák/*
21f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák * Copyright © 2008 Jérôme Glisse
31f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák * Copyright © 2010 Marek Olšák <maraeo@gmail.com>
41f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák * All Rights Reserved.
51f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák *
61f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák * Permission is hereby granted, free of charge, to any person obtaining
71f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák * a copy of this software and associated documentation files (the
81f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák * "Software"), to deal in the Software without restriction, including
91f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák * without limitation the rights to use, copy, modify, merge, publish,
101f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák * distribute, sub license, and/or sell copies of the Software, and to
111f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák * permit persons to whom the Software is furnished to do so, subject to
121f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák * the following conditions:
131f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák *
141f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
151f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
161f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
171f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS
181f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
191f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
201f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
211f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák * USE OR OTHER DEALINGS IN THE SOFTWARE.
221f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák *
231f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák * The above copyright notice and this permission notice (including the
241f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák * next paragraph) shall be included in all copies or substantial portions
251f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák * of the Software.
261f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák */
271f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák/*
281f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák * Authors:
291f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák *      Marek Olšák <maraeo@gmail.com>
301f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák *
311f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák * Based on work from libdrm_radeon by:
321f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák *      Aapo Tahkola <aet@rasterburn.org>
331f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák *      Nicolai Haehnle <prefect_@gmx.net>
341f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák *      Jérôme Glisse <glisse@freedesktop.org>
351f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák */
361f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
371f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák/*
381f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    This file replaces libdrm's radeon_cs_gem with our own implemention.
39d35aeff4bb0b03450b2c3c08bd7f84db5bf43283Marek Olšák    It's optimized specifically for Radeon DRM.
401f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    Reloc writes and space checking are faster and simpler than their
411f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    counterparts in libdrm (the time complexity of all the functions
421f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    is O(1) in nearly all scenarios, thanks to hashing).
431f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
441f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    It works like this:
451f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
461f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    cs_add_reloc(cs, buf, read_domain, write_domain) adds a new relocation and
471f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    also adds the size of 'buf' to the used_gart and used_vram winsys variables
481f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    based on the domains, which are simply or'd for the accounting purposes.
491f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    The adding is skipped if the reloc is already present in the list, but it
501f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    accounts any newly-referenced domains.
511f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
521f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    cs_validate is then called, which just checks:
531f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák        used_vram/gart < vram/gart_size * 0.8
541f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    The 0.8 number allows for some memory fragmentation. If the validation
551f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    fails, the pipe driver flushes CS and tries do the validation again,
561f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    i.e. it validates only that one operation. If it fails again, it drops
571f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    the operation on the floor and prints some nasty message to stderr.
581f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    (done in the pipe driver)
591f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
601f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    cs_write_reloc(cs, buf) just writes a reloc that has been added using
611f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    cs_add_reloc. The read_domain and write_domain parameters have been removed,
621f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    because we already specify them in cs_add_reloc.
631f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák*/
641f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
651f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák#include "radeon_drm_cs.h"
661f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
671f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák#include "util/u_memory.h"
681f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
696ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák#include <stdio.h>
701f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák#include <stdlib.h>
711f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák#include <stdint.h>
721f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák#include <xf86drm.h>
731f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
74bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse/*
75bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse * this are copy from radeon_drm, once an updated libdrm is released
76bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse * we should bump configure.ac requirement for it and remove the following
77bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse * field
78bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse */
7941b75dc92c921c078e64962f47b3d51b1e4f7b5aMarek Olšák#ifndef RADEON_CHUNK_ID_FLAGS
80bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse#define RADEON_CHUNK_ID_FLAGS       0x03
8141b75dc92c921c078e64962f47b3d51b1e4f7b5aMarek Olšák
8241b75dc92c921c078e64962f47b3d51b1e4f7b5aMarek Olšák/* The first dword of RADEON_CHUNK_ID_FLAGS is a uint32 of these flags: */
8341b75dc92c921c078e64962f47b3d51b1e4f7b5aMarek Olšák#define RADEON_CS_KEEP_TILING_FLAGS 0x01
8492af184690995d3b16731518f7becfaac3538edbChristian König
8592af184690995d3b16731518f7becfaac3538edbChristian König
8641b75dc92c921c078e64962f47b3d51b1e4f7b5aMarek Olšák#endif
8741b75dc92c921c078e64962f47b3d51b1e4f7b5aMarek Olšák
88bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse#ifndef RADEON_CS_USE_VM
89bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse#define RADEON_CS_USE_VM            0x02
90bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse/* The second dword of RADEON_CHUNK_ID_FLAGS is a uint32 that sets the ring type */
91bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse#define RADEON_CS_RING_GFX          0
92bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse#define RADEON_CS_RING_COMPUTE      1
93bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse#endif
94bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
95bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse
961f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák#define RELOC_DWORDS (sizeof(struct drm_radeon_cs_reloc) / sizeof(uint32_t))
971f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
98bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glissestatic boolean radeon_init_cs_context(struct radeon_cs_context *csc,
99bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse                                      struct radeon_drm_winsys *ws)
100b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák{
101bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    csc->fd = ws->fd;
102b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    csc->nrelocs = 512;
103b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    csc->relocs_bo = (struct radeon_bo**)
104b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák                     CALLOC(1, csc->nrelocs * sizeof(struct radeon_bo*));
105b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    if (!csc->relocs_bo) {
106b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák        return FALSE;
107b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    }
108b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák
109b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    csc->relocs = (struct drm_radeon_cs_reloc*)
110b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák                  CALLOC(1, csc->nrelocs * sizeof(struct drm_radeon_cs_reloc));
111b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    if (!csc->relocs) {
112b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák        FREE(csc->relocs_bo);
113b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák        return FALSE;
114b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    }
115b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák
116b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    csc->chunks[0].chunk_id = RADEON_CHUNK_ID_IB;
117b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    csc->chunks[0].length_dw = 0;
118b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    csc->chunks[0].chunk_data = (uint64_t)(uintptr_t)csc->buf;
119b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    csc->chunks[1].chunk_id = RADEON_CHUNK_ID_RELOCS;
120b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    csc->chunks[1].length_dw = 0;
121b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    csc->chunks[1].chunk_data = (uint64_t)(uintptr_t)csc->relocs;
12241b75dc92c921c078e64962f47b3d51b1e4f7b5aMarek Olšák    csc->chunks[2].chunk_id = RADEON_CHUNK_ID_FLAGS;
12392af184690995d3b16731518f7becfaac3538edbChristian König    csc->chunks[2].length_dw = 2;
12441b75dc92c921c078e64962f47b3d51b1e4f7b5aMarek Olšák    csc->chunks[2].chunk_data = (uint64_t)(uintptr_t)&csc->flags;
125b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák
126b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    csc->chunk_array[0] = (uint64_t)(uintptr_t)&csc->chunks[0];
127b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    csc->chunk_array[1] = (uint64_t)(uintptr_t)&csc->chunks[1];
12841b75dc92c921c078e64962f47b3d51b1e4f7b5aMarek Olšák    csc->chunk_array[2] = (uint64_t)(uintptr_t)&csc->chunks[2];
129b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák
130b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    csc->cs.chunks = (uint64_t)(uintptr_t)csc->chunk_array;
131b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    return TRUE;
132b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák}
133b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák
134b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšákstatic void radeon_cs_context_cleanup(struct radeon_cs_context *csc)
135b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák{
136b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    unsigned i;
137b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák
138b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    for (i = 0; i < csc->crelocs; i++) {
139b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák        p_atomic_dec(&csc->relocs_bo[i]->num_cs_references);
140c35572352e3e92683988ee8d151b47f4190d62f9Marek Olšák        radeon_bo_reference(&csc->relocs_bo[i], NULL);
141b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    }
142b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák
143b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    csc->crelocs = 0;
14464ab39b035f755510a644643b96451431bbe5f27Marek Olšák    csc->validated_crelocs = 0;
145b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    csc->chunks[0].length_dw = 0;
146b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    csc->chunks[1].length_dw = 0;
147b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    csc->used_gart = 0;
148b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    csc->used_vram = 0;
149b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    memset(csc->is_handle_added, 0, sizeof(csc->is_handle_added));
150b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák}
151b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák
152b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšákstatic void radeon_destroy_cs_context(struct radeon_cs_context *csc)
153b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák{
154b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    radeon_cs_context_cleanup(csc);
155b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    FREE(csc->relocs_bo);
156b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    FREE(csc->relocs);
157b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák}
158b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák
159210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten LankhorstDEBUG_GET_ONCE_BOOL_OPTION(thread, "RADEON_THREAD", TRUE)
160210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorststatic PIPE_THREAD_ROUTINE(radeon_drm_cs_emit_ioctl, param);
161210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorst
162d35aeff4bb0b03450b2c3c08bd7f84db5bf43283Marek Olšákstatic struct radeon_winsys_cs *radeon_drm_cs_create(struct radeon_winsys *rws)
1631f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák{
1641f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    struct radeon_drm_winsys *ws = radeon_drm_winsys(rws);
1651f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    struct radeon_drm_cs *cs;
1661f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
1671f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    cs = CALLOC_STRUCT(radeon_drm_cs);
1681f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    if (!cs) {
1691f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák        return NULL;
1701f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    }
171210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorst    pipe_semaphore_init(&cs->flush_queued, 0);
172210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorst    pipe_semaphore_init(&cs->flush_completed, 0);
1731f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
1741f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    cs->ws = ws;
175b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák
176bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    if (!radeon_init_cs_context(&cs->csc1, cs->ws)) {
1771f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák        FREE(cs);
1781f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák        return NULL;
1791f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    }
180bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse    if (!radeon_init_cs_context(&cs->csc2, cs->ws)) {
181b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák        radeon_destroy_cs_context(&cs->csc1);
1821f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák        FREE(cs);
1831f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák        return NULL;
1841f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    }
1851f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
186b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    /* Set the first command buffer as current. */
187b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    cs->csc = &cs->csc1;
188b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    cs->cst = &cs->csc2;
189b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    cs->base.buf = cs->csc->buf;
190b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák
191df54b53b7d12a3bca5867b6649cb308feb36f0daMarek Olšák    p_atomic_inc(&ws->num_cs);
192210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorst    if (cs->ws->num_cpus > 1 && debug_get_option_thread())
193210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorst        cs->thread = pipe_thread_create(radeon_drm_cs_emit_ioctl, cs);
1941f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    return &cs->base;
1951f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák}
1961f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
1971f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák#define OUT_CS(cs, value) (cs)->buf[(cs)->cdw++] = (value)
1981f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
199363ff844753c46ac9c13866627e096b091ea81f8Marek Olšákstatic INLINE void update_reloc_domains(struct drm_radeon_cs_reloc *reloc,
20093f4e3cb6c1ca303ee1f5c2a2491a8eff33f2633Marek Olšák                                        enum radeon_bo_domain rd,
20193f4e3cb6c1ca303ee1f5c2a2491a8eff33f2633Marek Olšák                                        enum radeon_bo_domain wd,
20293f4e3cb6c1ca303ee1f5c2a2491a8eff33f2633Marek Olšák                                        enum radeon_bo_domain *added_domains)
2031f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák{
20493f4e3cb6c1ca303ee1f5c2a2491a8eff33f2633Marek Olšák    *added_domains = (rd | wd) & ~(reloc->read_domains | reloc->write_domain);
20593f4e3cb6c1ca303ee1f5c2a2491a8eff33f2633Marek Olšák
20693f4e3cb6c1ca303ee1f5c2a2491a8eff33f2633Marek Olšák    reloc->read_domains |= rd;
20793f4e3cb6c1ca303ee1f5c2a2491a8eff33f2633Marek Olšák    reloc->write_domain |= wd;
2081f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák}
2091f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
210b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšákint radeon_get_reloc(struct radeon_cs_context *csc, struct radeon_bo *bo)
2111f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák{
2121f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    struct drm_radeon_cs_reloc *reloc;
2131f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    unsigned i;
214b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    unsigned hash = bo->handle & (sizeof(csc->is_handle_added)-1);
2151f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
216b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    if (csc->is_handle_added[hash]) {
217f6a66a33f7ba52e36242db9346573bf477efa04eVadim Girlin        i = csc->reloc_indices_hashlist[hash];
218f6a66a33f7ba52e36242db9346573bf477efa04eVadim Girlin        reloc = &csc->relocs[i];
2191f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák        if (reloc->handle == bo->handle) {
220f6a66a33f7ba52e36242db9346573bf477efa04eVadim Girlin            return i;
2211f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák        }
2221f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
2231f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák        /* Hash collision, look for the BO in the list of relocs linearly. */
224b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák        for (i = csc->crelocs; i != 0;) {
2251f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák            --i;
226b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák            reloc = &csc->relocs[i];
2271f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák            if (reloc->handle == bo->handle) {
2281f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák                /* Put this reloc in the hash list.
2291f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák                 * This will prevent additional hash collisions if there are
23093f4e3cb6c1ca303ee1f5c2a2491a8eff33f2633Marek Olšák                 * several consecutive get_reloc calls for the same buffer.
2311f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák                 *
2321f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák                 * Example: Assuming buffers A,B,C collide in the hash list,
2331f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák                 * the following sequence of relocs:
2341f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák                 *         AAAAAAAAAAABBBBBBBBBBBBBBCCCCCCCC
2351f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák                 * will collide here: ^ and here:   ^,
2361f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák                 * meaning that we should get very few collisions in the end. */
237b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák                csc->reloc_indices_hashlist[hash] = i;
2381f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák                /*printf("write_reloc collision, hash: %i, handle: %i\n", hash, bo->handle);*/
2391f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák                return i;
2401f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák            }
2411f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák        }
2421f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    }
2431f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
2441f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    return -1;
2451f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák}
2461f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
247638d75185e66727faaba5dc2df1b6e14c7c0c075Marek Olšákstatic unsigned radeon_add_reloc(struct radeon_cs_context *csc,
248638d75185e66727faaba5dc2df1b6e14c7c0c075Marek Olšák                                 struct radeon_bo *bo,
249363ff844753c46ac9c13866627e096b091ea81f8Marek Olšák                                 enum radeon_bo_usage usage,
25093f4e3cb6c1ca303ee1f5c2a2491a8eff33f2633Marek Olšák                                 enum radeon_bo_domain domains,
25193f4e3cb6c1ca303ee1f5c2a2491a8eff33f2633Marek Olšák                                 enum radeon_bo_domain *added_domains)
2521f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák{
2531f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    struct drm_radeon_cs_reloc *reloc;
2541f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    unsigned i;
255b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    unsigned hash = bo->handle & (sizeof(csc->is_handle_added)-1);
25693f4e3cb6c1ca303ee1f5c2a2491a8eff33f2633Marek Olšák    enum radeon_bo_domain rd = usage & RADEON_USAGE_READ ? domains : 0;
25793f4e3cb6c1ca303ee1f5c2a2491a8eff33f2633Marek Olšák    enum radeon_bo_domain wd = usage & RADEON_USAGE_WRITE ? domains : 0;
2581f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
259b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    if (csc->is_handle_added[hash]) {
260f6a66a33f7ba52e36242db9346573bf477efa04eVadim Girlin        i = csc->reloc_indices_hashlist[hash];
261f6a66a33f7ba52e36242db9346573bf477efa04eVadim Girlin        reloc = &csc->relocs[i];
2621f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák        if (reloc->handle == bo->handle) {
26393f4e3cb6c1ca303ee1f5c2a2491a8eff33f2633Marek Olšák            update_reloc_domains(reloc, rd, wd, added_domains);
264f6a66a33f7ba52e36242db9346573bf477efa04eVadim Girlin            return i;
2651f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák        }
2661f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
2671f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák        /* Hash collision, look for the BO in the list of relocs linearly. */
268b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák        for (i = csc->crelocs; i != 0;) {
2691f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák            --i;
270b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák            reloc = &csc->relocs[i];
2711f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák            if (reloc->handle == bo->handle) {
27293f4e3cb6c1ca303ee1f5c2a2491a8eff33f2633Marek Olšák                update_reloc_domains(reloc, rd, wd, added_domains);
2731f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
274b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák                csc->reloc_indices_hashlist[hash] = i;
2751f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák                /*printf("write_reloc collision, hash: %i, handle: %i\n", hash, bo->handle);*/
276638d75185e66727faaba5dc2df1b6e14c7c0c075Marek Olšák                return i;
2771f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák            }
2781f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák        }
2791f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    }
2801f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
2811f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    /* New relocation, check if the backing array is large enough. */
282b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    if (csc->crelocs >= csc->nrelocs) {
2831f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák        uint32_t size;
284b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák        csc->nrelocs += 10;
2851f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
286b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák        size = csc->nrelocs * sizeof(struct radeon_bo*);
287b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák        csc->relocs_bo = (struct radeon_bo**)realloc(csc->relocs_bo, size);
2881f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
289b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák        size = csc->nrelocs * sizeof(struct drm_radeon_cs_reloc);
290b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák        csc->relocs = (struct drm_radeon_cs_reloc*)realloc(csc->relocs, size);
2911f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
292b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák        csc->chunks[1].chunk_data = (uint64_t)(uintptr_t)csc->relocs;
2931f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    }
2941f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
2951f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    /* Initialize the new relocation. */
296aac4bae98651c928ce298aecf158b0aa1a7fabceMarek Olšák    csc->relocs_bo[csc->crelocs] = NULL;
297c35572352e3e92683988ee8d151b47f4190d62f9Marek Olšák    radeon_bo_reference(&csc->relocs_bo[csc->crelocs], bo);
298aac4bae98651c928ce298aecf158b0aa1a7fabceMarek Olšák    p_atomic_inc(&bo->num_cs_references);
299b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    reloc = &csc->relocs[csc->crelocs];
3001f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    reloc->handle = bo->handle;
30193f4e3cb6c1ca303ee1f5c2a2491a8eff33f2633Marek Olšák    reloc->read_domains = rd;
30293f4e3cb6c1ca303ee1f5c2a2491a8eff33f2633Marek Olšák    reloc->write_domain = wd;
3031f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    reloc->flags = 0;
3041f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
305b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    csc->is_handle_added[hash] = TRUE;
306b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    csc->reloc_indices_hashlist[hash] = csc->crelocs;
3071f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
308b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    csc->chunks[1].length_dw += RELOC_DWORDS;
3091f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
31093f4e3cb6c1ca303ee1f5c2a2491a8eff33f2633Marek Olšák    *added_domains = rd | wd;
311638d75185e66727faaba5dc2df1b6e14c7c0c075Marek Olšák    return csc->crelocs++;
3121f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák}
3131f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
31403b25ad8ffd72f1f88b6c80a2ebfe3cf6e8a6390Marek Olšákstatic unsigned radeon_drm_cs_add_reloc(struct radeon_winsys_cs *rcs,
31503b25ad8ffd72f1f88b6c80a2ebfe3cf6e8a6390Marek Olšák                                        struct radeon_winsys_cs_handle *buf,
31693f4e3cb6c1ca303ee1f5c2a2491a8eff33f2633Marek Olšák                                        enum radeon_bo_usage usage,
31793f4e3cb6c1ca303ee1f5c2a2491a8eff33f2633Marek Olšák                                        enum radeon_bo_domain domains)
3181f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák{
3191f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    struct radeon_drm_cs *cs = radeon_drm_cs(rcs);
3201f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    struct radeon_bo *bo = (struct radeon_bo*)buf;
32193f4e3cb6c1ca303ee1f5c2a2491a8eff33f2633Marek Olšák    enum radeon_bo_domain added_domains;
3221f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
32393f4e3cb6c1ca303ee1f5c2a2491a8eff33f2633Marek Olšák    unsigned index = radeon_add_reloc(cs->csc, bo, usage, domains, &added_domains);
3241f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
32593f4e3cb6c1ca303ee1f5c2a2491a8eff33f2633Marek Olšák    if (added_domains & RADEON_DOMAIN_GTT)
326a3cd2c6c9b3724dbc3aa565dab98968c46bde963Marek Olšák        cs->csc->used_gart += bo->base.size;
32793f4e3cb6c1ca303ee1f5c2a2491a8eff33f2633Marek Olšák    if (added_domains & RADEON_DOMAIN_VRAM)
328a3cd2c6c9b3724dbc3aa565dab98968c46bde963Marek Olšák        cs->csc->used_vram += bo->base.size;
32903b25ad8ffd72f1f88b6c80a2ebfe3cf6e8a6390Marek Olšák
33003b25ad8ffd72f1f88b6c80a2ebfe3cf6e8a6390Marek Olšák    return index;
3311f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák}
3321f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
333d35aeff4bb0b03450b2c3c08bd7f84db5bf43283Marek Olšákstatic boolean radeon_drm_cs_validate(struct radeon_winsys_cs *rcs)
3341f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák{
3351f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    struct radeon_drm_cs *cs = radeon_drm_cs(rcs);
33664ab39b035f755510a644643b96451431bbe5f27Marek Olšák    boolean status =
33764ab39b035f755510a644643b96451431bbe5f27Marek Olšák        cs->csc->used_gart < cs->ws->info.gart_size * 0.8 &&
33864ab39b035f755510a644643b96451431bbe5f27Marek Olšák        cs->csc->used_vram < cs->ws->info.vram_size * 0.8;
3391f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
34064ab39b035f755510a644643b96451431bbe5f27Marek Olšák    if (status) {
34164ab39b035f755510a644643b96451431bbe5f27Marek Olšák        cs->csc->validated_crelocs = cs->csc->crelocs;
34264ab39b035f755510a644643b96451431bbe5f27Marek Olšák    } else {
34364ab39b035f755510a644643b96451431bbe5f27Marek Olšák        /* Remove lately-added relocations. The validation failed with them
34464ab39b035f755510a644643b96451431bbe5f27Marek Olšák         * and the CS is about to be flushed because of that. Keep only
34564ab39b035f755510a644643b96451431bbe5f27Marek Olšák         * the already-validated relocations. */
34664ab39b035f755510a644643b96451431bbe5f27Marek Olšák        unsigned i;
34764ab39b035f755510a644643b96451431bbe5f27Marek Olšák
34864ab39b035f755510a644643b96451431bbe5f27Marek Olšák        for (i = cs->csc->validated_crelocs; i < cs->csc->crelocs; i++) {
34964ab39b035f755510a644643b96451431bbe5f27Marek Olšák            p_atomic_dec(&cs->csc->relocs_bo[i]->num_cs_references);
35064ab39b035f755510a644643b96451431bbe5f27Marek Olšák            radeon_bo_reference(&cs->csc->relocs_bo[i], NULL);
35164ab39b035f755510a644643b96451431bbe5f27Marek Olšák        }
35264ab39b035f755510a644643b96451431bbe5f27Marek Olšák        cs->csc->crelocs = cs->csc->validated_crelocs;
35364ab39b035f755510a644643b96451431bbe5f27Marek Olšák
35464ab39b035f755510a644643b96451431bbe5f27Marek Olšák        /* Flush if there are any relocs. Clean up otherwise. */
35564ab39b035f755510a644643b96451431bbe5f27Marek Olšák        if (cs->csc->crelocs) {
35664ab39b035f755510a644643b96451431bbe5f27Marek Olšák            cs->flush_cs(cs->flush_data, RADEON_FLUSH_ASYNC);
35764ab39b035f755510a644643b96451431bbe5f27Marek Olšák        } else {
35864ab39b035f755510a644643b96451431bbe5f27Marek Olšák            radeon_cs_context_cleanup(cs->csc);
35964ab39b035f755510a644643b96451431bbe5f27Marek Olšák
36064ab39b035f755510a644643b96451431bbe5f27Marek Olšák            assert(cs->base.cdw == 0);
36164ab39b035f755510a644643b96451431bbe5f27Marek Olšák            if (cs->base.cdw != 0) {
36264ab39b035f755510a644643b96451431bbe5f27Marek Olšák                fprintf(stderr, "radeon: Unexpected error in %s.\n", __func__);
36364ab39b035f755510a644643b96451431bbe5f27Marek Olšák            }
36464ab39b035f755510a644643b96451431bbe5f27Marek Olšák        }
36564ab39b035f755510a644643b96451431bbe5f27Marek Olšák    }
36664ab39b035f755510a644643b96451431bbe5f27Marek Olšák    return status;
3671f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák}
3681f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
36978222e63630280b96488de0d51d1b2578e26f814Jerome Glissestatic boolean radeon_drm_cs_memory_below_limit(struct radeon_winsys_cs *rcs, uint64_t vram, uint64_t gtt)
37078222e63630280b96488de0d51d1b2578e26f814Jerome Glisse{
37178222e63630280b96488de0d51d1b2578e26f814Jerome Glisse    struct radeon_drm_cs *cs = radeon_drm_cs(rcs);
37278222e63630280b96488de0d51d1b2578e26f814Jerome Glisse    boolean status =
37378222e63630280b96488de0d51d1b2578e26f814Jerome Glisse        (cs->csc->used_gart + gtt) < cs->ws->info.gart_size * 0.7 &&
37478222e63630280b96488de0d51d1b2578e26f814Jerome Glisse        (cs->csc->used_vram + vram) < cs->ws->info.vram_size * 0.7;
37578222e63630280b96488de0d51d1b2578e26f814Jerome Glisse
37678222e63630280b96488de0d51d1b2578e26f814Jerome Glisse    return status;
37778222e63630280b96488de0d51d1b2578e26f814Jerome Glisse}
37878222e63630280b96488de0d51d1b2578e26f814Jerome Glisse
379d35aeff4bb0b03450b2c3c08bd7f84db5bf43283Marek Olšákstatic void radeon_drm_cs_write_reloc(struct radeon_winsys_cs *rcs,
380d35aeff4bb0b03450b2c3c08bd7f84db5bf43283Marek Olšák                                      struct radeon_winsys_cs_handle *buf)
3811f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák{
3821f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    struct radeon_drm_cs *cs = radeon_drm_cs(rcs);
3831f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    struct radeon_bo *bo = (struct radeon_bo*)buf;
3841f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
385b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    unsigned index = radeon_get_reloc(cs->csc, bo);
3861f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
3871f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    if (index == -1) {
3889d5de0fcb6ced7a4da85a09ad25dcbc2b21bfdf9Marek Olšák        fprintf(stderr, "radeon: Cannot get a relocation in %s.\n", __func__);
3891f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák        return;
3901f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    }
3911f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
3921f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    OUT_CS(&cs->base, 0xc0001000);
3931f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    OUT_CS(&cs->base, index * RELOC_DWORDS);
3941f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák}
3951f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
396210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorststatic void radeon_drm_cs_emit_ioctl_oneshot(struct radeon_cs_context *csc)
3971f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák{
3981f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    unsigned i;
3991f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
400b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    if (drmCommandWriteRead(csc->fd, DRM_RADEON_CS,
401b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák                            &csc->cs, sizeof(struct drm_radeon_cs))) {
402b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák        if (debug_get_bool_option("RADEON_DUMP_CS", FALSE)) {
403b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák            unsigned i;
404b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák
405b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák            fprintf(stderr, "radeon: The kernel rejected CS, dumping...\n");
406b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák            for (i = 0; i < csc->chunks[0].length_dw; i++) {
407b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák                fprintf(stderr, "0x%08X\n", csc->buf[i]);
4081f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák            }
409b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák        } else {
410b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák            fprintf(stderr, "radeon: The kernel rejected CS, "
411b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák                    "see dmesg for more information.\n");
4121f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák        }
4131f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    }
4141f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
415b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    for (i = 0; i < csc->crelocs; i++)
416b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák        p_atomic_dec(&csc->relocs_bo[i]->num_active_ioctls);
4175b005ecc2b624a0ffb577ab760abacf069694f8dMarek Olšák
4185b005ecc2b624a0ffb577ab760abacf069694f8dMarek Olšák    radeon_cs_context_cleanup(csc);
419210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorst}
420210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorst
421210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorststatic PIPE_THREAD_ROUTINE(radeon_drm_cs_emit_ioctl, param)
422210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorst{
423210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorst    struct radeon_drm_cs *cs = (struct radeon_drm_cs*)param;
424210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorst
425210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorst    while (1) {
426210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorst        pipe_semaphore_wait(&cs->flush_queued);
427210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorst        if (cs->kill_thread)
428210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorst            break;
429210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorst        radeon_drm_cs_emit_ioctl_oneshot(cs->cst);
430210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorst        pipe_semaphore_signal(&cs->flush_completed);
431210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorst    }
432210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorst    pipe_semaphore_signal(&cs->flush_completed);
433b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    return NULL;
434b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák}
435b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák
4365650a719f0c69c00954e47bd7a7b3e9433cb551dMarek Olšákvoid radeon_drm_cs_sync_flush(struct radeon_drm_cs *cs)
437b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák{
438b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    /* Wait for any pending ioctl to complete. */
439210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorst    if (cs->thread && cs->flush_started) {
440210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorst        pipe_semaphore_wait(&cs->flush_completed);
441210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorst        cs->flush_started = 0;
4421f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    }
443b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák}
444b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák
445d35aeff4bb0b03450b2c3c08bd7f84db5bf43283Marek Olšákstatic void radeon_drm_cs_flush(struct radeon_winsys_cs *rcs, unsigned flags)
446b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák{
447b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    struct radeon_drm_cs *cs = radeon_drm_cs(rcs);
448b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    struct radeon_cs_context *tmp;
449b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák
450a7f4d3b740d4c85b0dc2b006c30c2bc4a3ed8597Marek Olšák    if (rcs->cdw > RADEON_MAX_CMDBUF_DWORDS) {
451a7f4d3b740d4c85b0dc2b006c30c2bc4a3ed8597Marek Olšák       fprintf(stderr, "radeon: command stream overflowed\n");
452a7f4d3b740d4c85b0dc2b006c30c2bc4a3ed8597Marek Olšák    }
453a7f4d3b740d4c85b0dc2b006c30c2bc4a3ed8597Marek Olšák
4545650a719f0c69c00954e47bd7a7b3e9433cb551dMarek Olšák    radeon_drm_cs_sync_flush(cs);
455b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák
456210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorst    /* Flip command streams. */
457210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorst    tmp = cs->csc;
458210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorst    cs->csc = cs->cst;
459210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorst    cs->cst = tmp;
460210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorst
461a7f4d3b740d4c85b0dc2b006c30c2bc4a3ed8597Marek Olšák    /* If the CS is not empty or overflowed, emit it in a separate thread. */
462a7f4d3b740d4c85b0dc2b006c30c2bc4a3ed8597Marek Olšák    if (cs->base.cdw && cs->base.cdw <= RADEON_MAX_CMDBUF_DWORDS) {
463210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorst        unsigned i, crelocs = cs->cst->crelocs;
464b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák
465210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorst        cs->cst->chunks[0].length_dw = cs->base.cdw;
466b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák
4676caac3ecb8bc32d92c35fdb1f0a67541ffa8af29Marek Olšák        for (i = 0; i < crelocs; i++) {
4686caac3ecb8bc32d92c35fdb1f0a67541ffa8af29Marek Olšák            /* Update the number of active asynchronous CS ioctls for the buffer. */
469210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorst            p_atomic_inc(&cs->cst->relocs_bo[i]->num_active_ioctls);
4706caac3ecb8bc32d92c35fdb1f0a67541ffa8af29Marek Olšák        }
4716caac3ecb8bc32d92c35fdb1f0a67541ffa8af29Marek Olšák
47292af184690995d3b16731518f7becfaac3538edbChristian König        cs->cst->flags[0] = 0;
47392af184690995d3b16731518f7becfaac3538edbChristian König        cs->cst->flags[1] = RADEON_CS_RING_GFX;
474bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse        cs->cst->cs.num_chunks = 2;
47541b75dc92c921c078e64962f47b3d51b1e4f7b5aMarek Olšák        if (flags & RADEON_FLUSH_KEEP_TILING_FLAGS) {
47692af184690995d3b16731518f7becfaac3538edbChristian König            cs->cst->flags[0] |= RADEON_CS_KEEP_TILING_FLAGS;
47741b75dc92c921c078e64962f47b3d51b1e4f7b5aMarek Olšák            cs->cst->cs.num_chunks = 3;
478bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse        }
479bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse        if (cs->ws->info.r600_virtual_address) {
48092af184690995d3b16731518f7becfaac3538edbChristian König            cs->cst->flags[0] |= RADEON_CS_USE_VM;
48192af184690995d3b16731518f7becfaac3538edbChristian König            cs->cst->cs.num_chunks = 3;
48292af184690995d3b16731518f7becfaac3538edbChristian König        }
48392af184690995d3b16731518f7becfaac3538edbChristian König        if (flags & RADEON_FLUSH_COMPUTE) {
48492af184690995d3b16731518f7becfaac3538edbChristian König            cs->cst->flags[1] = RADEON_CS_RING_COMPUTE;
485bb1f0cf3508630a9a93512c79badf8c493c46743Jerome Glisse            cs->cst->cs.num_chunks = 3;
48641b75dc92c921c078e64962f47b3d51b1e4f7b5aMarek Olšák        }
48741b75dc92c921c078e64962f47b3d51b1e4f7b5aMarek Olšák
488210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorst        if (cs->thread &&
489d35aeff4bb0b03450b2c3c08bd7f84db5bf43283Marek Olšák            (flags & RADEON_FLUSH_ASYNC)) {
490210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorst            cs->flush_started = 1;
491210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorst            pipe_semaphore_signal(&cs->flush_queued);
492b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák        } else {
493210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorst            radeon_drm_cs_emit_ioctl_oneshot(cs->cst);
494b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák        }
4955b005ecc2b624a0ffb577ab760abacf069694f8dMarek Olšák    } else {
496210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorst        radeon_cs_context_cleanup(cs->cst);
497b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    }
498b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák
499b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    /* Prepare a new CS. */
500b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    cs->base.buf = cs->csc->buf;
5011f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    cs->base.cdw = 0;
5021f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák}
5031f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
504d35aeff4bb0b03450b2c3c08bd7f84db5bf43283Marek Olšákstatic void radeon_drm_cs_destroy(struct radeon_winsys_cs *rcs)
5051f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák{
5061f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    struct radeon_drm_cs *cs = radeon_drm_cs(rcs);
5075650a719f0c69c00954e47bd7a7b3e9433cb551dMarek Olšák    radeon_drm_cs_sync_flush(cs);
508210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorst    if (cs->thread) {
509210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorst        cs->kill_thread = 1;
510210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorst        pipe_semaphore_signal(&cs->flush_queued);
511210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorst        pipe_semaphore_wait(&cs->flush_completed);
512210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorst        pipe_thread_wait(cs->thread);
513210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorst    }
514210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorst    pipe_semaphore_destroy(&cs->flush_queued);
515210ddf0819b5acf87a614214b6d4b02193aafa4aMaarten Lankhorst    pipe_semaphore_destroy(&cs->flush_completed);
516b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    radeon_cs_context_cleanup(&cs->csc1);
517b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    radeon_cs_context_cleanup(&cs->csc2);
518df54b53b7d12a3bca5867b6649cb308feb36f0daMarek Olšák    p_atomic_dec(&cs->ws->num_cs);
519b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    radeon_destroy_cs_context(&cs->csc1);
520b9e2cde6006b557a3a23a82384899f4d5a5ac7b8Marek Olšák    radeon_destroy_cs_context(&cs->csc2);
5211f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    FREE(cs);
5221f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák}
5231f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
524d35aeff4bb0b03450b2c3c08bd7f84db5bf43283Marek Olšákstatic void radeon_drm_cs_set_flush(struct radeon_winsys_cs *rcs,
5255650a719f0c69c00954e47bd7a7b3e9433cb551dMarek Olšák                                    void (*flush)(void *ctx, unsigned flags),
5265650a719f0c69c00954e47bd7a7b3e9433cb551dMarek Olšák                                    void *user)
5271f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák{
5281f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    struct radeon_drm_cs *cs = radeon_drm_cs(rcs);
5291f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    cs->flush_cs = flush;
5301f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    cs->flush_data = user;
5311f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák}
5321f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák
533d35aeff4bb0b03450b2c3c08bd7f84db5bf43283Marek Olšákstatic boolean radeon_bo_is_referenced(struct radeon_winsys_cs *rcs,
53429e55bc5f1b6d7375b6a86e24ca4ae58e399011eMarek Olšák                                       struct radeon_winsys_cs_handle *_buf,
53529e55bc5f1b6d7375b6a86e24ca4ae58e399011eMarek Olšák                                       enum radeon_bo_usage usage)
5366ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák{
5376ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    struct radeon_drm_cs *cs = radeon_drm_cs(rcs);
5386ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    struct radeon_bo *bo = (struct radeon_bo*)_buf;
53929e55bc5f1b6d7375b6a86e24ca4ae58e399011eMarek Olšák    int index;
5406ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
54129e55bc5f1b6d7375b6a86e24ca4ae58e399011eMarek Olšák    if (!bo->num_cs_references)
54229e55bc5f1b6d7375b6a86e24ca4ae58e399011eMarek Olšák        return FALSE;
54329e55bc5f1b6d7375b6a86e24ca4ae58e399011eMarek Olšák
54429e55bc5f1b6d7375b6a86e24ca4ae58e399011eMarek Olšák    index = radeon_get_reloc(cs->csc, bo);
54529e55bc5f1b6d7375b6a86e24ca4ae58e399011eMarek Olšák    if (index == -1)
54629e55bc5f1b6d7375b6a86e24ca4ae58e399011eMarek Olšák        return FALSE;
54729e55bc5f1b6d7375b6a86e24ca4ae58e399011eMarek Olšák
54829e55bc5f1b6d7375b6a86e24ca4ae58e399011eMarek Olšák    if ((usage & RADEON_USAGE_WRITE) && cs->csc->relocs[index].write_domain)
54929e55bc5f1b6d7375b6a86e24ca4ae58e399011eMarek Olšák        return TRUE;
55029e55bc5f1b6d7375b6a86e24ca4ae58e399011eMarek Olšák    if ((usage & RADEON_USAGE_READ) && cs->csc->relocs[index].read_domains)
55129e55bc5f1b6d7375b6a86e24ca4ae58e399011eMarek Olšák        return TRUE;
55229e55bc5f1b6d7375b6a86e24ca4ae58e399011eMarek Olšák
55329e55bc5f1b6d7375b6a86e24ca4ae58e399011eMarek Olšák    return FALSE;
5546ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák}
5556ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák
5561f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšákvoid radeon_drm_cs_init_functions(struct radeon_drm_winsys *ws)
5571f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák{
5581f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    ws->base.cs_create = radeon_drm_cs_create;
5591f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    ws->base.cs_destroy = radeon_drm_cs_destroy;
5601f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    ws->base.cs_add_reloc = radeon_drm_cs_add_reloc;
5611f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    ws->base.cs_validate = radeon_drm_cs_validate;
56278222e63630280b96488de0d51d1b2578e26f814Jerome Glisse    ws->base.cs_memory_below_limit = radeon_drm_cs_memory_below_limit;
5631f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák    ws->base.cs_write_reloc = radeon_drm_cs_write_reloc;
564fa3f1348e49feeac511dbe5b22bbddc47f56ba81Marek Olšák    ws->base.cs_flush = radeon_drm_cs_flush;
565e2e1dc9e66ff348caa97b7b35e558d75c6cc6899Marek Olšák    ws->base.cs_set_flush_callback = radeon_drm_cs_set_flush;
5666ccab620a0e7364ab6c0d902b3ddf58ee988f7faMarek Olšák    ws->base.cs_is_buffer_referenced = radeon_bo_is_referenced;
5671f0348c4a2ba4f8ca812a2daccf3b01c3f984ef1Marek Olšák}
568