103b705cfSriastradh/*
203b705cfSriastradh * Copyright (c) 2011 Intel Corporation
303b705cfSriastradh *
403b705cfSriastradh * Permission is hereby granted, free of charge, to any person obtaining a
503b705cfSriastradh * copy of this software and associated documentation files (the "Software"),
603b705cfSriastradh * to deal in the Software without restriction, including without limitation
703b705cfSriastradh * the rights to use, copy, modify, merge, publish, distribute, sublicense,
803b705cfSriastradh * and/or sell copies of the Software, and to permit persons to whom the
903b705cfSriastradh * Software is furnished to do so, subject to the following conditions:
1003b705cfSriastradh *
1103b705cfSriastradh * The above copyright notice and this permission notice (including the next
1203b705cfSriastradh * paragraph) shall be included in all copies or substantial portions of the
1303b705cfSriastradh * Software.
1403b705cfSriastradh *
1503b705cfSriastradh * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1603b705cfSriastradh * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1703b705cfSriastradh * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1803b705cfSriastradh * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1903b705cfSriastradh * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2003b705cfSriastradh * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2103b705cfSriastradh * SOFTWARE.
2203b705cfSriastradh *
2303b705cfSriastradh * Authors:
2403b705cfSriastradh *    Chris Wilson <chris@chris-wilson.co.uk>
2503b705cfSriastradh *
2603b705cfSriastradh */
2703b705cfSriastradh
2803b705cfSriastradh#ifndef KGEM_H
2903b705cfSriastradh#define KGEM_H
3003b705cfSriastradh
3103b705cfSriastradh#include <stdint.h>
3203b705cfSriastradh#include <stdbool.h>
3303b705cfSriastradh#include <stdarg.h>
3403b705cfSriastradh
3503b705cfSriastradh#include <i915_drm.h>
3603b705cfSriastradh
3703b705cfSriastradh#include "compiler.h"
3813496ba1Ssnj#include "debug.h"
3903b705cfSriastradh
4003b705cfSriastradhstruct kgem_bo {
4103b705cfSriastradh	struct kgem_request *rq;
4203b705cfSriastradh#define RQ(rq) ((struct kgem_request *)((uintptr_t)(rq) & ~3))
4303b705cfSriastradh#define RQ_RING(rq) ((uintptr_t)(rq) & 3)
4403b705cfSriastradh#define RQ_IS_BLT(rq) (RQ_RING(rq) == KGEM_BLT)
45fe8aea9eSmrg#define RQ_IS_RENDER(rq) (RQ_RING(rq) == KGEM_RENDER)
4642542f5fSchristos#define MAKE_REQUEST(rq, ring) ((struct kgem_request *)((uintptr_t)(rq) | (ring)))
4742542f5fSchristos
4803b705cfSriastradh	struct drm_i915_gem_exec_object2 *exec;
4903b705cfSriastradh
5003b705cfSriastradh	struct kgem_bo *proxy;
5103b705cfSriastradh
5203b705cfSriastradh	struct list list;
5303b705cfSriastradh	struct list request;
5403b705cfSriastradh	struct list vma;
5503b705cfSriastradh
5642542f5fSchristos	void *map__cpu;
5742542f5fSchristos	void *map__gtt;
5813496ba1Ssnj	void *map__wc;
5903b705cfSriastradh#define MAP(ptr) ((void*)((uintptr_t)(ptr) & ~3))
6003b705cfSriastradh
6103b705cfSriastradh	struct kgem_bo_binding {
6203b705cfSriastradh		struct kgem_bo_binding *next;
6303b705cfSriastradh		uint32_t format;
6403b705cfSriastradh		uint16_t offset;
6503b705cfSriastradh	} binding;
6603b705cfSriastradh
6742542f5fSchristos	uint64_t presumed_offset;
6803b705cfSriastradh	uint32_t unique_id;
6903b705cfSriastradh	uint32_t refcnt;
7003b705cfSriastradh	uint32_t handle;
7103b705cfSriastradh	uint32_t target_handle;
7203b705cfSriastradh	uint32_t delta;
7342542f5fSchristos	uint32_t active_scanout;
7403b705cfSriastradh	union {
7503b705cfSriastradh		struct {
7603b705cfSriastradh			uint32_t count:27;
7703b705cfSriastradh#define PAGE_SIZE 4096
7803b705cfSriastradh			uint32_t bucket:5;
7903b705cfSriastradh#define NUM_CACHE_BUCKETS 16
8003b705cfSriastradh#define MAX_CACHE_SIZE (1 << (NUM_CACHE_BUCKETS+12))
8103b705cfSriastradh		} pages;
8203b705cfSriastradh		uint32_t bytes;
8303b705cfSriastradh	} size;
8403b705cfSriastradh	uint32_t pitch : 18; /* max 128k */
8503b705cfSriastradh	uint32_t tiling : 2;
8603b705cfSriastradh	uint32_t reusable : 1;
8703b705cfSriastradh	uint32_t gpu_dirty : 1;
8803b705cfSriastradh	uint32_t gtt_dirty : 1;
8903b705cfSriastradh	uint32_t domain : 2;
9003b705cfSriastradh	uint32_t needs_flush : 1;
9103b705cfSriastradh	uint32_t snoop : 1;
9203b705cfSriastradh	uint32_t io : 1;
9303b705cfSriastradh	uint32_t flush : 1;
9403b705cfSriastradh	uint32_t scanout : 1;
9542542f5fSchristos	uint32_t prime : 1;
9603b705cfSriastradh	uint32_t purged : 1;
9703b705cfSriastradh};
9803b705cfSriastradh#define DOMAIN_NONE 0
9903b705cfSriastradh#define DOMAIN_CPU 1
10003b705cfSriastradh#define DOMAIN_GTT 2
10103b705cfSriastradh#define DOMAIN_GPU 3
10203b705cfSriastradh
10303b705cfSriastradhstruct kgem_request {
10403b705cfSriastradh	struct list list;
10503b705cfSriastradh	struct kgem_bo *bo;
10603b705cfSriastradh	struct list buffers;
107fe8aea9eSmrg	unsigned ring;
10803b705cfSriastradh};
10903b705cfSriastradh
11003b705cfSriastradhenum {
11103b705cfSriastradh	MAP_GTT = 0,
11203b705cfSriastradh	MAP_CPU,
11303b705cfSriastradh	NUM_MAP_TYPES,
11403b705cfSriastradh};
11503b705cfSriastradh
116fe8aea9eSmrgtypedef void (*memcpy_box_func)(const void *src, void *dst, int bpp,
117fe8aea9eSmrg				int32_t src_stride, int32_t dst_stride,
118fe8aea9eSmrg				int16_t src_x, int16_t src_y,
119fe8aea9eSmrg				int16_t dst_x, int16_t dst_y,
120fe8aea9eSmrg				uint16_t width, uint16_t height);
121fe8aea9eSmrg
12203b705cfSriastradhstruct kgem {
12342542f5fSchristos	unsigned wedged;
12413496ba1Ssnj	int fd;
12503b705cfSriastradh	unsigned gen;
12603b705cfSriastradh
12703b705cfSriastradh	uint32_t unique_id;
12803b705cfSriastradh
12913496ba1Ssnj	uint16_t nbatch;
13013496ba1Ssnj	uint16_t surface;
13113496ba1Ssnj	uint16_t nexec;
13213496ba1Ssnj	uint16_t nreloc;
13313496ba1Ssnj	uint16_t nreloc__self;
13413496ba1Ssnj	uint16_t nfence;
13513496ba1Ssnj	uint16_t batch_size;
13613496ba1Ssnj
13713496ba1Ssnj	uint32_t *batch;
13813496ba1Ssnj
13903b705cfSriastradh	enum kgem_mode {
14003b705cfSriastradh		/* order matches I915_EXEC_RING ordering */
14103b705cfSriastradh		KGEM_NONE = 0,
14203b705cfSriastradh		KGEM_RENDER,
14303b705cfSriastradh		KGEM_BSD,
14403b705cfSriastradh		KGEM_BLT,
14503b705cfSriastradh	} mode, ring;
14603b705cfSriastradh
14703b705cfSriastradh	struct list flushing;
14803b705cfSriastradh	struct list large;
14903b705cfSriastradh	struct list large_inactive;
15003b705cfSriastradh	struct list active[NUM_CACHE_BUCKETS][3];
15103b705cfSriastradh	struct list inactive[NUM_CACHE_BUCKETS];
15203b705cfSriastradh	struct list pinned_batches[2];
15303b705cfSriastradh	struct list snoop;
15403b705cfSriastradh	struct list scanout;
15503b705cfSriastradh	struct list batch_buffers, active_buffers;
15603b705cfSriastradh
15703b705cfSriastradh	struct list requests[2];
15813496ba1Ssnj	struct kgem_request *fence[2];
15903b705cfSriastradh	struct kgem_request *next_request;
16003b705cfSriastradh	struct kgem_request static_request;
16103b705cfSriastradh
16203b705cfSriastradh	struct {
16303b705cfSriastradh		struct list inactive[NUM_CACHE_BUCKETS];
16403b705cfSriastradh		int16_t count;
16503b705cfSriastradh	} vma[NUM_MAP_TYPES];
16603b705cfSriastradh
167fe8aea9eSmrg	uint32_t bcs_state;
168fe8aea9eSmrg
16903b705cfSriastradh	uint32_t batch_flags;
17003b705cfSriastradh	uint32_t batch_flags_base;
17103b705cfSriastradh#define I915_EXEC_SECURE (1<<9)
17203b705cfSriastradh#define LOCAL_EXEC_OBJECT_WRITE (1<<2)
17303b705cfSriastradh
17403b705cfSriastradh	uint32_t flush:1;
17503b705cfSriastradh	uint32_t need_expire:1;
17603b705cfSriastradh	uint32_t need_purge:1;
17703b705cfSriastradh	uint32_t need_retire:1;
17803b705cfSriastradh	uint32_t need_throttle:1;
17942542f5fSchristos	uint32_t needs_semaphore:1;
18042542f5fSchristos	uint32_t needs_reservation:1;
18103b705cfSriastradh	uint32_t scanout_busy:1;
18203b705cfSriastradh	uint32_t busy:1;
18303b705cfSriastradh
18403b705cfSriastradh	uint32_t has_create2 :1;
18503b705cfSriastradh	uint32_t has_userptr :1;
18603b705cfSriastradh	uint32_t has_blt :1;
18703b705cfSriastradh	uint32_t has_relaxed_fencing :1;
18803b705cfSriastradh	uint32_t has_relaxed_delta :1;
18903b705cfSriastradh	uint32_t has_semaphores :1;
19003b705cfSriastradh	uint32_t has_secure_batches :1;
19103b705cfSriastradh	uint32_t has_pinned_batches :1;
19203b705cfSriastradh	uint32_t has_caching :1;
193fe8aea9eSmrg	uint32_t has_coherent_mmap_gtt :1;
19403b705cfSriastradh	uint32_t has_llc :1;
19503b705cfSriastradh	uint32_t has_wt :1;
19603b705cfSriastradh	uint32_t has_no_reloc :1;
19703b705cfSriastradh	uint32_t has_handle_lut :1;
19813496ba1Ssnj	uint32_t has_wc_mmap :1;
199fe8aea9eSmrg	uint32_t has_dirtyfb :1;
20003b705cfSriastradh
201fe8aea9eSmrg	uint32_t can_fence :1;
20203b705cfSriastradh	uint32_t can_blt_cpu :1;
203fe8aea9eSmrg	uint32_t can_blt_y :1;
20442542f5fSchristos	uint32_t can_render_y :1;
205fe8aea9eSmrg	uint32_t can_scanout_y :1;
206fe8aea9eSmrg
207fe8aea9eSmrg	uint32_t needs_dirtyfb :1;
20803b705cfSriastradh
20903b705cfSriastradh	uint16_t fence_max;
21003b705cfSriastradh	uint16_t half_cpu_cache_pages;
21142542f5fSchristos	uint32_t aperture_total, aperture_high, aperture_low, aperture_mappable, aperture_fenceable;
21242542f5fSchristos	uint32_t aperture, aperture_fenced, aperture_max_fence;
21303b705cfSriastradh	uint32_t max_upload_tile_size, max_copy_tile_size;
21403b705cfSriastradh	uint32_t max_gpu_size, max_cpu_size;
21503b705cfSriastradh	uint32_t large_object_size, max_object_size;
21603b705cfSriastradh	uint32_t buffer_size;
21703b705cfSriastradh
21803b705cfSriastradh	void (*context_switch)(struct kgem *kgem, int new_mode);
21903b705cfSriastradh	void (*retire)(struct kgem *kgem);
22003b705cfSriastradh	void (*expire)(struct kgem *kgem);
22103b705cfSriastradh
222fe8aea9eSmrg	memcpy_box_func memcpy_to_tiled_x;
223fe8aea9eSmrg	memcpy_box_func memcpy_from_tiled_x;
224fe8aea9eSmrg	memcpy_box_func memcpy_between_tiled_x;
22503b705cfSriastradh
22613496ba1Ssnj	struct kgem_bo *batch_bo;
22713496ba1Ssnj
22803b705cfSriastradh	uint16_t reloc__self[256];
22903b705cfSriastradh	struct drm_i915_gem_exec_object2 exec[384] page_aligned;
23003b705cfSriastradh	struct drm_i915_gem_relocation_entry reloc[8192] page_aligned;
23103b705cfSriastradh
23203b705cfSriastradh#ifdef DEBUG_MEMORY
23303b705cfSriastradh	struct {
23403b705cfSriastradh		int bo_allocs;
23503b705cfSriastradh		size_t bo_bytes;
23603b705cfSriastradh	} debug_memory;
23703b705cfSriastradh#endif
23803b705cfSriastradh};
23903b705cfSriastradh
24003b705cfSriastradh#define KGEM_MAX_DEFERRED_VBO 16
24103b705cfSriastradh
242fe8aea9eSmrg#define KGEM_BATCH_RESERVED 8 /* LRI(SWCTRL) + END */
24303b705cfSriastradh#define KGEM_RELOC_RESERVED (KGEM_MAX_DEFERRED_VBO)
24403b705cfSriastradh#define KGEM_EXEC_RESERVED (1+KGEM_MAX_DEFERRED_VBO)
24503b705cfSriastradh
24603b705cfSriastradh#ifndef ARRAY_SIZE
24703b705cfSriastradh#define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
24803b705cfSriastradh#endif
24903b705cfSriastradh
25003b705cfSriastradh#define KGEM_BATCH_SIZE(K) ((K)->batch_size-KGEM_BATCH_RESERVED)
25103b705cfSriastradh#define KGEM_EXEC_SIZE(K) (int)(ARRAY_SIZE((K)->exec)-KGEM_EXEC_RESERVED)
25203b705cfSriastradh#define KGEM_RELOC_SIZE(K) (int)(ARRAY_SIZE((K)->reloc)-KGEM_RELOC_RESERVED)
25303b705cfSriastradh
25403b705cfSriastradhvoid kgem_init(struct kgem *kgem, int fd, struct pci_device *dev, unsigned gen);
25503b705cfSriastradhvoid kgem_reset(struct kgem *kgem);
25603b705cfSriastradh
25703b705cfSriastradhstruct kgem_bo *kgem_create_map(struct kgem *kgem,
25803b705cfSriastradh				void *ptr, uint32_t size,
25903b705cfSriastradh				bool read_only);
26003b705cfSriastradh
26103b705cfSriastradhstruct kgem_bo *kgem_create_for_name(struct kgem *kgem, uint32_t name);
26203b705cfSriastradhstruct kgem_bo *kgem_create_for_prime(struct kgem *kgem, int name, uint32_t size);
26303b705cfSriastradhint kgem_bo_export_to_prime(struct kgem *kgem, struct kgem_bo *bo);
26403b705cfSriastradh
26503b705cfSriastradhstruct kgem_bo *kgem_create_linear(struct kgem *kgem, int size, unsigned flags);
26603b705cfSriastradhstruct kgem_bo *kgem_create_proxy(struct kgem *kgem,
26703b705cfSriastradh				  struct kgem_bo *target,
26803b705cfSriastradh				  int offset, int length);
26903b705cfSriastradh
27003b705cfSriastradhstruct kgem_bo *kgem_upload_source_image(struct kgem *kgem,
27103b705cfSriastradh					 const void *data,
27203b705cfSriastradh					 const BoxRec *box,
27303b705cfSriastradh					 int stride, int bpp);
27403b705cfSriastradhvoid kgem_proxy_bo_attach(struct kgem_bo *bo, struct kgem_bo **ptr);
27503b705cfSriastradh
27603b705cfSriastradhint kgem_choose_tiling(struct kgem *kgem,
27703b705cfSriastradh		       int tiling, int width, int height, int bpp);
27803b705cfSriastradhunsigned kgem_can_create_2d(struct kgem *kgem, int width, int height, int depth);
27903b705cfSriastradh#define KGEM_CAN_CREATE_GPU	0x1
28003b705cfSriastradh#define KGEM_CAN_CREATE_CPU	0x2
28103b705cfSriastradh#define KGEM_CAN_CREATE_LARGE	0x4
28203b705cfSriastradh#define KGEM_CAN_CREATE_GTT	0x8
28342542f5fSchristos#define KGEM_CAN_CREATE_TILED	0x10
28403b705cfSriastradh
28542542f5fSchristosbool kgem_check_surface_size(struct kgem *kgem,
28642542f5fSchristos			     uint32_t width,
28742542f5fSchristos			     uint32_t height,
28842542f5fSchristos			     uint32_t bpp,
28942542f5fSchristos			     uint32_t tiling,
29042542f5fSchristos			     uint32_t pitch,
29142542f5fSchristos			     uint32_t size);
29203b705cfSriastradh
29303b705cfSriastradhstruct kgem_bo *
29403b705cfSriastradhkgem_replace_bo(struct kgem *kgem,
29503b705cfSriastradh		struct kgem_bo *src,
29603b705cfSriastradh		uint32_t width,
29703b705cfSriastradh		uint32_t height,
29803b705cfSriastradh		uint32_t pitch,
29903b705cfSriastradh		uint32_t bpp);
30003b705cfSriastradhenum {
30103b705cfSriastradh	CREATE_EXACT = 0x1,
30203b705cfSriastradh	CREATE_INACTIVE = 0x2,
30303b705cfSriastradh	CREATE_CPU_MAP = 0x4,
30403b705cfSriastradh	CREATE_GTT_MAP = 0x8,
30503b705cfSriastradh	CREATE_SCANOUT = 0x10,
30603b705cfSriastradh	CREATE_PRIME = 0x20,
30703b705cfSriastradh	CREATE_TEMPORARY = 0x40,
30803b705cfSriastradh	CREATE_CACHED = 0x80,
30913496ba1Ssnj	CREATE_UNCACHED = 0x100,
31013496ba1Ssnj	CREATE_NO_RETIRE = 0x200,
31113496ba1Ssnj	CREATE_NO_THROTTLE = 0x400,
31203b705cfSriastradh};
31303b705cfSriastradhstruct kgem_bo *kgem_create_2d(struct kgem *kgem,
31403b705cfSriastradh			       int width,
31503b705cfSriastradh			       int height,
31603b705cfSriastradh			       int bpp,
31703b705cfSriastradh			       int tiling,
31803b705cfSriastradh			       uint32_t flags);
31903b705cfSriastradhstruct kgem_bo *kgem_create_cpu_2d(struct kgem *kgem,
32003b705cfSriastradh				   int width,
32103b705cfSriastradh				   int height,
32203b705cfSriastradh				   int bpp,
32303b705cfSriastradh				   uint32_t flags);
32403b705cfSriastradh
32542542f5fSchristosbool kgem_bo_convert_to_gpu(struct kgem *kgem,
32642542f5fSchristos			    struct kgem_bo *bo,
32742542f5fSchristos			    unsigned flags);
32842542f5fSchristos
329fe8aea9eSmrgbool kgem_bo_is_fenced(struct kgem *kgem, struct kgem_bo *bo);
33003b705cfSriastradhuint32_t kgem_bo_get_binding(struct kgem_bo *bo, uint32_t format);
33103b705cfSriastradhvoid kgem_bo_set_binding(struct kgem_bo *bo, uint32_t format, uint16_t offset);
33203b705cfSriastradh
33303b705cfSriastradhbool kgem_retire(struct kgem *kgem);
33442542f5fSchristosvoid kgem_retire__buffers(struct kgem *kgem);
33542542f5fSchristos
33642542f5fSchristosstatic inline bool kgem_bo_discard_cache(struct kgem_bo *bo, bool force)
33742542f5fSchristos{
33842542f5fSchristos	if (bo == NULL || bo->proxy == NULL)
33942542f5fSchristos		return false;
34042542f5fSchristos
34142542f5fSchristos	if (force)
34242542f5fSchristos		return true;
34342542f5fSchristos
34442542f5fSchristos	if (bo->proxy->rq)
34542542f5fSchristos		return false;
34642542f5fSchristos
34742542f5fSchristos	return bo->snoop;
34842542f5fSchristos}
34903b705cfSriastradh
35003b705cfSriastradhbool __kgem_ring_is_idle(struct kgem *kgem, int ring);
35103b705cfSriastradhstatic inline bool kgem_ring_is_idle(struct kgem *kgem, int ring)
35203b705cfSriastradh{
35303b705cfSriastradh	ring = ring == KGEM_BLT;
35403b705cfSriastradh
355fe8aea9eSmrg	if (kgem->needs_semaphore &&
356fe8aea9eSmrg	    !list_is_empty(&kgem->requests[!ring]) &&
357fe8aea9eSmrg	    !__kgem_ring_is_idle(kgem, !ring))
358fe8aea9eSmrg		return false;
359fe8aea9eSmrg
36003b705cfSriastradh	if (list_is_empty(&kgem->requests[ring]))
36103b705cfSriastradh		return true;
36203b705cfSriastradh
36303b705cfSriastradh	return __kgem_ring_is_idle(kgem, ring);
36403b705cfSriastradh}
36503b705cfSriastradh
36603b705cfSriastradhstatic inline bool kgem_is_idle(struct kgem *kgem)
36703b705cfSriastradh{
36803b705cfSriastradh	if (!kgem->need_retire)
36903b705cfSriastradh		return true;
37003b705cfSriastradh
37103b705cfSriastradh	return kgem_ring_is_idle(kgem, kgem->ring);
37203b705cfSriastradh}
37303b705cfSriastradh
37403b705cfSriastradhstatic inline bool __kgem_ring_empty(struct kgem *kgem)
37503b705cfSriastradh{
37603b705cfSriastradh	return list_is_empty(&kgem->requests[kgem->ring == KGEM_BLT]);
37703b705cfSriastradh}
37803b705cfSriastradh
37903b705cfSriastradhvoid _kgem_submit(struct kgem *kgem);
38003b705cfSriastradhstatic inline void kgem_submit(struct kgem *kgem)
38103b705cfSriastradh{
38203b705cfSriastradh	if (kgem->nbatch)
38303b705cfSriastradh		_kgem_submit(kgem);
38403b705cfSriastradh}
38503b705cfSriastradh
38603b705cfSriastradhstatic inline void kgem_bo_submit(struct kgem *kgem, struct kgem_bo *bo)
38703b705cfSriastradh{
38842542f5fSchristos	if (bo->exec == NULL)
38942542f5fSchristos		return;
39042542f5fSchristos
39142542f5fSchristos	assert(bo->refcnt);
39242542f5fSchristos	_kgem_submit(kgem);
39303b705cfSriastradh}
39403b705cfSriastradh
39503b705cfSriastradhvoid kgem_scanout_flush(struct kgem *kgem, struct kgem_bo *bo);
39603b705cfSriastradh
39703b705cfSriastradhstatic inline struct kgem_bo *kgem_bo_reference(struct kgem_bo *bo)
39803b705cfSriastradh{
39903b705cfSriastradh	assert(bo->refcnt);
40003b705cfSriastradh	bo->refcnt++;
40103b705cfSriastradh	return bo;
40203b705cfSriastradh}
40303b705cfSriastradh
40403b705cfSriastradhvoid _kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo);
40503b705cfSriastradhstatic inline void kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo)
40603b705cfSriastradh{
40703b705cfSriastradh	assert(bo->refcnt);
408fe8aea9eSmrg	assert(bo->refcnt > bo->active_scanout);
40903b705cfSriastradh	if (--bo->refcnt == 0)
41003b705cfSriastradh		_kgem_bo_destroy(kgem, bo);
41103b705cfSriastradh}
41203b705cfSriastradh
41303b705cfSriastradhvoid kgem_clear_dirty(struct kgem *kgem);
41403b705cfSriastradh
41503b705cfSriastradhstatic inline void kgem_set_mode(struct kgem *kgem,
41603b705cfSriastradh				 enum kgem_mode mode,
41703b705cfSriastradh				 struct kgem_bo *bo)
41803b705cfSriastradh{
419fe8aea9eSmrg	warn_unless(!kgem->wedged);
42003b705cfSriastradh
42103b705cfSriastradh#if DEBUG_FLUSH_BATCH
42203b705cfSriastradh	kgem_submit(kgem);
42303b705cfSriastradh#endif
42403b705cfSriastradh
425fe8aea9eSmrg	if (kgem->nreloc && bo->rq == NULL && kgem_ring_is_idle(kgem, kgem->ring)) {
42642542f5fSchristos		DBG(("%s: flushing before new bo\n", __FUNCTION__));
42703b705cfSriastradh		_kgem_submit(kgem);
42842542f5fSchristos	}
42903b705cfSriastradh
43003b705cfSriastradh	if (kgem->mode == mode)
43103b705cfSriastradh		return;
43203b705cfSriastradh
43303b705cfSriastradh	kgem->context_switch(kgem, mode);
43403b705cfSriastradh	kgem->mode = mode;
43503b705cfSriastradh}
43603b705cfSriastradh
43703b705cfSriastradhstatic inline void _kgem_set_mode(struct kgem *kgem, enum kgem_mode mode)
43803b705cfSriastradh{
43903b705cfSriastradh	assert(kgem->mode == KGEM_NONE);
44003b705cfSriastradh	assert(kgem->nbatch == 0);
441fe8aea9eSmrg	warn_unless(!kgem->wedged);
44203b705cfSriastradh	kgem->context_switch(kgem, mode);
44303b705cfSriastradh	kgem->mode = mode;
44403b705cfSriastradh}
44503b705cfSriastradh
44613496ba1Ssnjstatic inline int kgem_batch_space(struct kgem *kgem)
44713496ba1Ssnj{
44813496ba1Ssnj	int rem = kgem->surface - kgem->nbatch;
44913496ba1Ssnj	assert(rem > 0);
45013496ba1Ssnj	return rem - KGEM_BATCH_RESERVED;
45113496ba1Ssnj}
45213496ba1Ssnj
45303b705cfSriastradhstatic inline bool kgem_check_batch(struct kgem *kgem, int num_dwords)
45403b705cfSriastradh{
45503b705cfSriastradh	assert(num_dwords > 0);
45603b705cfSriastradh	assert(kgem->nbatch < kgem->surface);
45703b705cfSriastradh	assert(kgem->surface <= kgem->batch_size);
45803b705cfSriastradh	return likely(kgem->nbatch + num_dwords + KGEM_BATCH_RESERVED <= kgem->surface);
45903b705cfSriastradh}
46003b705cfSriastradh
46103b705cfSriastradhstatic inline bool kgem_check_reloc(struct kgem *kgem, int n)
46203b705cfSriastradh{
46303b705cfSriastradh	assert(kgem->nreloc <= KGEM_RELOC_SIZE(kgem));
46403b705cfSriastradh	return likely(kgem->nreloc + n <= KGEM_RELOC_SIZE(kgem));
46503b705cfSriastradh}
46603b705cfSriastradh
46703b705cfSriastradhstatic inline bool kgem_check_exec(struct kgem *kgem, int n)
46803b705cfSriastradh{
46903b705cfSriastradh	assert(kgem->nexec <= KGEM_EXEC_SIZE(kgem));
47003b705cfSriastradh	return likely(kgem->nexec + n <= KGEM_EXEC_SIZE(kgem));
47103b705cfSriastradh}
47203b705cfSriastradh
47303b705cfSriastradhstatic inline bool kgem_check_reloc_and_exec(struct kgem *kgem, int n)
47403b705cfSriastradh{
47503b705cfSriastradh	return kgem_check_reloc(kgem, n) && kgem_check_exec(kgem, n);
47603b705cfSriastradh}
47703b705cfSriastradh
47803b705cfSriastradhstatic inline bool kgem_check_batch_with_surfaces(struct kgem *kgem,
47903b705cfSriastradh						  int num_dwords,
48003b705cfSriastradh						  int num_surfaces)
48103b705cfSriastradh{
48203b705cfSriastradh	return (int)(kgem->nbatch + num_dwords + KGEM_BATCH_RESERVED) <= (int)(kgem->surface - num_surfaces*8) &&
48303b705cfSriastradh		kgem_check_reloc(kgem, num_surfaces) &&
48403b705cfSriastradh		kgem_check_exec(kgem, num_surfaces);
48503b705cfSriastradh}
48603b705cfSriastradh
48703b705cfSriastradhstatic inline uint32_t *kgem_get_batch(struct kgem *kgem)
48803b705cfSriastradh{
48903b705cfSriastradh	if (kgem->nreloc) {
49003b705cfSriastradh		unsigned mode = kgem->mode;
49103b705cfSriastradh		_kgem_submit(kgem);
49203b705cfSriastradh		_kgem_set_mode(kgem, mode);
49303b705cfSriastradh	}
49403b705cfSriastradh
49503b705cfSriastradh	return kgem->batch + kgem->nbatch;
49603b705cfSriastradh}
49703b705cfSriastradh
49803b705cfSriastradhbool kgem_check_bo(struct kgem *kgem, ...) __attribute__((sentinel(0)));
49903b705cfSriastradhbool kgem_check_bo_fenced(struct kgem *kgem, struct kgem_bo *bo);
50003b705cfSriastradhbool kgem_check_many_bo_fenced(struct kgem *kgem, ...) __attribute__((sentinel(0)));
50103b705cfSriastradh
50203b705cfSriastradh#define KGEM_RELOC_FENCED 0x8000
50303b705cfSriastradhuint32_t kgem_add_reloc(struct kgem *kgem,
50403b705cfSriastradh			uint32_t pos,
50503b705cfSriastradh			struct kgem_bo *bo,
50603b705cfSriastradh			uint32_t read_write_domains,
50703b705cfSriastradh			uint32_t delta);
50842542f5fSchristosuint64_t kgem_add_reloc64(struct kgem *kgem,
50942542f5fSchristos			  uint32_t pos,
51042542f5fSchristos			  struct kgem_bo *bo,
51142542f5fSchristos			  uint32_t read_write_domains,
51242542f5fSchristos			  uint64_t delta);
51303b705cfSriastradh
51403b705cfSriastradhvoid *kgem_bo_map(struct kgem *kgem, struct kgem_bo *bo);
51503b705cfSriastradhvoid *kgem_bo_map__async(struct kgem *kgem, struct kgem_bo *bo);
51603b705cfSriastradhvoid *kgem_bo_map__gtt(struct kgem *kgem, struct kgem_bo *bo);
51713496ba1Ssnjvoid *kgem_bo_map__wc(struct kgem *kgem, struct kgem_bo *bo);
51803b705cfSriastradhvoid kgem_bo_sync__gtt(struct kgem *kgem, struct kgem_bo *bo);
51903b705cfSriastradhvoid *kgem_bo_map__debug(struct kgem *kgem, struct kgem_bo *bo);
52003b705cfSriastradhvoid *kgem_bo_map__cpu(struct kgem *kgem, struct kgem_bo *bo);
52103b705cfSriastradhvoid kgem_bo_sync__cpu(struct kgem *kgem, struct kgem_bo *bo);
52203b705cfSriastradhvoid kgem_bo_sync__cpu_full(struct kgem *kgem, struct kgem_bo *bo, bool write);
52303b705cfSriastradhuint32_t kgem_bo_flink(struct kgem *kgem, struct kgem_bo *bo);
52403b705cfSriastradh
52503b705cfSriastradhbool kgem_bo_write(struct kgem *kgem, struct kgem_bo *bo,
52603b705cfSriastradh		   const void *data, int length);
52703b705cfSriastradh
52803b705cfSriastradhint kgem_bo_fenced_size(struct kgem *kgem, struct kgem_bo *bo);
52942542f5fSchristosvoid kgem_get_tile_size(struct kgem *kgem, int tiling, int pitch,
53003b705cfSriastradh			int *tile_width, int *tile_height, int *tile_size);
53103b705cfSriastradh
53203b705cfSriastradhstatic inline int __kgem_buffer_size(struct kgem_bo *bo)
53303b705cfSriastradh{
53403b705cfSriastradh	assert(bo->proxy != NULL);
53503b705cfSriastradh	return bo->size.bytes;
53603b705cfSriastradh}
53703b705cfSriastradh
53803b705cfSriastradhstatic inline int __kgem_bo_size(struct kgem_bo *bo)
53903b705cfSriastradh{
54003b705cfSriastradh	assert(bo->proxy == NULL);
54103b705cfSriastradh	return PAGE_SIZE * bo->size.pages.count;
54203b705cfSriastradh}
54303b705cfSriastradh
54442542f5fSchristosstatic inline int __kgem_bo_num_pages(struct kgem_bo *bo)
54542542f5fSchristos{
54642542f5fSchristos	assert(bo->proxy == NULL);
54742542f5fSchristos	return bo->size.pages.count;
54842542f5fSchristos}
54942542f5fSchristos
55003b705cfSriastradhstatic inline int kgem_bo_size(struct kgem_bo *bo)
55103b705cfSriastradh{
55203b705cfSriastradh	if (bo->proxy)
55303b705cfSriastradh		return __kgem_buffer_size(bo);
55403b705cfSriastradh	else
55503b705cfSriastradh		return __kgem_bo_size(bo);
55603b705cfSriastradh}
55703b705cfSriastradh
55803b705cfSriastradhstatic inline bool kgem_bo_blt_pitch_is_ok(struct kgem *kgem,
55903b705cfSriastradh					   struct kgem_bo *bo)
56003b705cfSriastradh{
56103b705cfSriastradh	int pitch = bo->pitch;
56213496ba1Ssnj
56313496ba1Ssnj	if (kgem->gen >= 0100 && pitch & (1 << 4)) { /* bdw is broken */
56413496ba1Ssnj		DBG(("%s: can not blt to handle=%d, pitch=%d\n",
56513496ba1Ssnj		     __FUNCTION__, bo->handle, pitch));
56613496ba1Ssnj		return false;
56713496ba1Ssnj	}
56813496ba1Ssnj
56903b705cfSriastradh	if (kgem->gen >= 040 && bo->tiling)
57003b705cfSriastradh		pitch /= 4;
57103b705cfSriastradh	if (pitch > MAXSHORT) {
57203b705cfSriastradh		DBG(("%s: can not blt to handle=%d, adjusted pitch=%d\n",
57303b705cfSriastradh		     __FUNCTION__, bo->handle, pitch));
57403b705cfSriastradh		return false;
57503b705cfSriastradh	}
57603b705cfSriastradh
57703b705cfSriastradh	return true;
57803b705cfSriastradh}
57903b705cfSriastradh
58003b705cfSriastradhstatic inline bool kgem_bo_can_blt(struct kgem *kgem,
58103b705cfSriastradh				   struct kgem_bo *bo)
58203b705cfSriastradh{
58342542f5fSchristos	assert(bo->refcnt);
58442542f5fSchristos
585fe8aea9eSmrg	if (bo->tiling == I915_TILING_Y && !kgem->can_blt_y) {
58603b705cfSriastradh		DBG(("%s: can not blt to handle=%d, tiling=Y\n",
58703b705cfSriastradh		     __FUNCTION__, bo->handle));
58803b705cfSriastradh		return false;
58903b705cfSriastradh	}
59003b705cfSriastradh
591fe8aea9eSmrg	if (kgem->gen >= 0100 && bo->proxy && bo->delta & 63) {
59213496ba1Ssnj		DBG(("%s: can not blt to handle=%d, delta=%d\n",
59313496ba1Ssnj		     __FUNCTION__, bo->handle, bo->delta));
59413496ba1Ssnj		return false;
59513496ba1Ssnj	}
59613496ba1Ssnj
59703b705cfSriastradh	return kgem_bo_blt_pitch_is_ok(kgem, bo);
59803b705cfSriastradh}
59903b705cfSriastradh
600fe8aea9eSmrgvoid __kgem_bcs_set_tiling(struct kgem *kgem,
601fe8aea9eSmrg			   struct kgem_bo *src,
602fe8aea9eSmrg			   struct kgem_bo *dst);
603fe8aea9eSmrg
604fe8aea9eSmrginline static void kgem_bcs_set_tiling(struct kgem *kgem,
605fe8aea9eSmrg				       struct kgem_bo *src,
606fe8aea9eSmrg				       struct kgem_bo *dst)
607fe8aea9eSmrg{
608fe8aea9eSmrg	assert(kgem->mode == KGEM_BLT);
609fe8aea9eSmrg
610fe8aea9eSmrg	if (!kgem->can_blt_y)
611fe8aea9eSmrg		return;
612fe8aea9eSmrg
613fe8aea9eSmrg	__kgem_bcs_set_tiling(kgem, src, dst);
614fe8aea9eSmrg}
615fe8aea9eSmrg
61603b705cfSriastradhstatic inline bool kgem_bo_is_snoop(struct kgem_bo *bo)
61703b705cfSriastradh{
61803b705cfSriastradh	assert(bo->refcnt);
61903b705cfSriastradh	while (bo->proxy)
62003b705cfSriastradh		bo = bo->proxy;
62103b705cfSriastradh	return bo->snoop;
62203b705cfSriastradh}
62303b705cfSriastradh
62403b705cfSriastradhvoid kgem_bo_undo(struct kgem *kgem, struct kgem_bo *bo);
62542542f5fSchristosvoid kgem_bo_pair_undo(struct kgem *kgem, struct kgem_bo *a, struct kgem_bo *b);
62603b705cfSriastradh
62703b705cfSriastradhbool __kgem_busy(struct kgem *kgem, int handle);
62803b705cfSriastradh
62942542f5fSchristosstatic inline void kgem_bo_mark_busy(struct kgem *kgem, struct kgem_bo *bo, int ring)
63003b705cfSriastradh{
63142542f5fSchristos	assert(bo->refcnt);
63242542f5fSchristos	bo->needs_flush = true;
63342542f5fSchristos	if (bo->rq) {
63442542f5fSchristos		bo->rq = MAKE_REQUEST(RQ(bo->rq), ring);
63542542f5fSchristos	} else {
63642542f5fSchristos		bo->rq = MAKE_REQUEST(kgem, ring);
63742542f5fSchristos		list_add(&bo->request, &kgem->flushing);
63842542f5fSchristos		kgem->need_retire = true;
63942542f5fSchristos	}
64003b705cfSriastradh}
64103b705cfSriastradh
642fe8aea9eSmrgstatic inline void __kgem_bo_clear_dirty(struct kgem_bo *bo)
64303b705cfSriastradh{
64442542f5fSchristos	DBG(("%s: handle=%d\n", __FUNCTION__, bo->handle));
64503b705cfSriastradh
64603b705cfSriastradh	bo->domain = DOMAIN_NONE;
64703b705cfSriastradh	bo->needs_flush = false;
64803b705cfSriastradh	bo->gtt_dirty = false;
64903b705cfSriastradh}
65003b705cfSriastradh
651fe8aea9eSmrginline static void __kgem_bo_clear_busy(struct kgem_bo *bo)
652fe8aea9eSmrg{
653fe8aea9eSmrg	DBG(("%s: handle=%d\n", __FUNCTION__, bo->handle));
654fe8aea9eSmrg	bo->rq = NULL;
655fe8aea9eSmrg	list_del(&bo->request);
656fe8aea9eSmrg
657fe8aea9eSmrg	__kgem_bo_clear_dirty(bo);
658fe8aea9eSmrg}
659fe8aea9eSmrg
66003b705cfSriastradhstatic inline bool kgem_bo_is_busy(struct kgem_bo *bo)
66103b705cfSriastradh{
66203b705cfSriastradh	DBG(("%s: handle=%d, domain: %d exec? %d, rq? %d\n", __FUNCTION__,
66303b705cfSriastradh	     bo->handle, bo->domain, bo->exec != NULL, bo->rq != NULL));
66403b705cfSriastradh	assert(bo->refcnt);
66503b705cfSriastradh	return bo->rq;
66603b705cfSriastradh}
66703b705cfSriastradh
668fe8aea9eSmrgbool __kgem_retire_requests_upto(struct kgem *kgem, struct kgem_bo *bo);
66903b705cfSriastradhstatic inline bool __kgem_bo_is_busy(struct kgem *kgem, struct kgem_bo *bo)
67003b705cfSriastradh{
67103b705cfSriastradh	DBG(("%s: handle=%d, domain: %d exec? %d, rq? %d\n", __FUNCTION__,
67203b705cfSriastradh	     bo->handle, bo->domain, bo->exec != NULL, bo->rq != NULL));
67303b705cfSriastradh	assert(bo->refcnt);
67403b705cfSriastradh
67503b705cfSriastradh	if (bo->exec)
67603b705cfSriastradh		return true;
67703b705cfSriastradh
678fe8aea9eSmrg	if (bo->rq == NULL)
679fe8aea9eSmrg		return false;
680fe8aea9eSmrg
681fe8aea9eSmrg	if (__kgem_busy(kgem, bo->handle))
682fe8aea9eSmrg		return true;
68303b705cfSriastradh
684fe8aea9eSmrg	return __kgem_retire_requests_upto(kgem, bo);
68503b705cfSriastradh}
68603b705cfSriastradh
68703b705cfSriastradhstatic inline bool kgem_bo_is_render(struct kgem_bo *bo)
68803b705cfSriastradh{
68903b705cfSriastradh	DBG(("%s: handle=%d, rq? %d [%d]\n", __FUNCTION__,
69042542f5fSchristos	     bo->handle, bo->rq != NULL, (int)RQ_RING(bo->rq)));
69103b705cfSriastradh	assert(bo->refcnt);
692fe8aea9eSmrg	return bo->rq && RQ_RING(bo->rq) != KGEM_BLT;
693fe8aea9eSmrg}
694fe8aea9eSmrg
695fe8aea9eSmrgstatic inline bool kgem_bo_is_blt(struct kgem_bo *bo)
696fe8aea9eSmrg{
697fe8aea9eSmrg	DBG(("%s: handle=%d, rq? %d\n", __FUNCTION__,
698fe8aea9eSmrg	     bo->handle, bo->rq != NULL, (int)RQ_RING(bo->rq)));
699fe8aea9eSmrg	assert(bo->refcnt);
700fe8aea9eSmrg	return RQ_RING(bo->rq) == KGEM_BLT;
70103b705cfSriastradh}
70203b705cfSriastradh
70303b705cfSriastradhstatic inline void kgem_bo_mark_unreusable(struct kgem_bo *bo)
70403b705cfSriastradh{
70542542f5fSchristos	assert(bo->refcnt);
70603b705cfSriastradh	while (bo->proxy) {
70703b705cfSriastradh		bo->flush = true;
70803b705cfSriastradh		bo = bo->proxy;
70942542f5fSchristos		assert(bo->refcnt);
71003b705cfSriastradh	}
71103b705cfSriastradh	bo->flush = true;
71203b705cfSriastradh	bo->reusable = false;
71303b705cfSriastradh}
71403b705cfSriastradh
71503b705cfSriastradhstatic inline bool kgem_bo_is_dirty(struct kgem_bo *bo)
71603b705cfSriastradh{
71703b705cfSriastradh	if (bo == NULL)
71803b705cfSriastradh		return false;
71903b705cfSriastradh
72003b705cfSriastradh	assert(bo->refcnt);
72103b705cfSriastradh	return bo->gpu_dirty;
72203b705cfSriastradh}
72303b705cfSriastradh
72403b705cfSriastradhstatic inline void kgem_bo_unclean(struct kgem *kgem, struct kgem_bo *bo)
72503b705cfSriastradh{
72603b705cfSriastradh	/* The bo is outside of our control, so presume it is written to */
72703b705cfSriastradh	bo->needs_flush = true;
72803b705cfSriastradh	if (bo->rq == NULL)
72903b705cfSriastradh		bo->rq = (void *)kgem;
73003b705cfSriastradh
73103b705cfSriastradh	if (bo->domain != DOMAIN_GPU)
73203b705cfSriastradh		bo->domain = DOMAIN_NONE;
73303b705cfSriastradh}
73403b705cfSriastradh
73503b705cfSriastradhstatic inline void __kgem_bo_mark_dirty(struct kgem_bo *bo)
73603b705cfSriastradh{
73703b705cfSriastradh	DBG(("%s: handle=%d (proxy? %d)\n", __FUNCTION__,
73803b705cfSriastradh	     bo->handle, bo->proxy != NULL));
73903b705cfSriastradh
74042542f5fSchristos	assert(bo->refcnt);
74142542f5fSchristos	assert(bo->exec);
74242542f5fSchristos	assert(bo->rq);
74342542f5fSchristos
74403b705cfSriastradh	bo->exec->flags |= LOCAL_EXEC_OBJECT_WRITE;
74503b705cfSriastradh	bo->needs_flush = bo->gpu_dirty = true;
74603b705cfSriastradh	list_move(&bo->request, &RQ(bo->rq)->buffers);
74703b705cfSriastradh}
74803b705cfSriastradh
74903b705cfSriastradhstatic inline void kgem_bo_mark_dirty(struct kgem_bo *bo)
75003b705cfSriastradh{
75103b705cfSriastradh	assert(bo->refcnt);
75203b705cfSriastradh	do {
75303b705cfSriastradh		assert(bo->exec);
75403b705cfSriastradh		assert(bo->rq);
75503b705cfSriastradh
75603b705cfSriastradh		if (bo->gpu_dirty)
75703b705cfSriastradh			return;
75803b705cfSriastradh
75903b705cfSriastradh		__kgem_bo_mark_dirty(bo);
76003b705cfSriastradh	} while ((bo = bo->proxy));
76103b705cfSriastradh}
76203b705cfSriastradh
76342542f5fSchristosstatic inline bool kgem_bo_mapped(struct kgem *kgem, struct kgem_bo *bo)
76442542f5fSchristos{
76542542f5fSchristos	DBG(("%s: handle=%d, map=%p:%p, tiling=%d, domain=%d\n",
76642542f5fSchristos	     __FUNCTION__, bo->handle, bo->map__gtt, bo->map__cpu, bo->tiling, bo->domain));
76742542f5fSchristos	assert(bo->proxy == NULL);
76842542f5fSchristos
76942542f5fSchristos	if (bo->tiling == I915_TILING_NONE && (bo->domain == DOMAIN_CPU || kgem->has_llc))
77042542f5fSchristos		return bo->map__cpu != NULL;
77142542f5fSchristos
77213496ba1Ssnj	if (bo->tiling == I915_TILING_NONE && bo->map__wc)
77313496ba1Ssnj		return true;
77413496ba1Ssnj
77542542f5fSchristos	return bo->map__gtt != NULL;
77642542f5fSchristos}
77742542f5fSchristos
77842542f5fSchristosstatic inline bool kgem_bo_can_map(struct kgem *kgem, struct kgem_bo *bo)
77942542f5fSchristos{
78013496ba1Ssnj	DBG(("%s: handle=%d, map=%p:%p:%p, tiling=%d, domain=%d, offset=%ld\n",
78113496ba1Ssnj	     __FUNCTION__, bo->handle, bo->map__gtt, bo->map__wc, bo->map__cpu, bo->tiling, bo->domain, (long)bo->presumed_offset));
78242542f5fSchristos
78342542f5fSchristos	if (!bo->tiling && (kgem->has_llc || bo->domain == DOMAIN_CPU))
78442542f5fSchristos		return true;
78542542f5fSchristos
78642542f5fSchristos	assert(bo->proxy == NULL);
78742542f5fSchristos
78842542f5fSchristos	if (bo->map__gtt != NULL)
78942542f5fSchristos		return true;
79042542f5fSchristos
79142542f5fSchristos	if (kgem->gen == 021 && bo->tiling == I915_TILING_Y)
79242542f5fSchristos		return false;
79342542f5fSchristos
79413496ba1Ssnj	if (!bo->tiling && kgem->has_wc_mmap)
79513496ba1Ssnj		return true;
79613496ba1Ssnj
79742542f5fSchristos	return __kgem_bo_num_pages(bo) <= kgem->aperture_mappable / 4;
79842542f5fSchristos}
79942542f5fSchristos
80042542f5fSchristosstatic inline bool kgem_bo_can_map__cpu(struct kgem *kgem,
80142542f5fSchristos					struct kgem_bo *bo,
80242542f5fSchristos					bool write)
80342542f5fSchristos{
80442542f5fSchristos	DBG(("%s: handle=%d\n", __FUNCTION__, bo->handle));
80542542f5fSchristos	assert(bo->refcnt);
80642542f5fSchristos
80742542f5fSchristos	if (bo->purged || (bo->scanout && write)) {
80842542f5fSchristos		DBG(("%s: no, writing to scanout? %d, or is stolen [inaccessible via CPU]? %d\n",
80942542f5fSchristos		     __FUNCTION__, bo->scanout && write, bo->purged));
81042542f5fSchristos		return false;
81142542f5fSchristos	}
81242542f5fSchristos
81342542f5fSchristos	if (kgem->has_llc) {
81442542f5fSchristos		DBG(("%s: yes, has LLC and target is in LLC\n", __FUNCTION__));
81542542f5fSchristos		return true;
81642542f5fSchristos	}
81742542f5fSchristos
81842542f5fSchristos	DBG(("%s: non-LLC - CPU domain? %d, clean? %d\n",
81942542f5fSchristos	     __FUNCTION__, bo->domain == DOMAIN_CPU, !write || bo->exec == NULL));
82042542f5fSchristos	if (bo->domain != DOMAIN_CPU)
82142542f5fSchristos		return false;
82242542f5fSchristos
82342542f5fSchristos	return !write || bo->exec == NULL;
82442542f5fSchristos}
82542542f5fSchristos
82603b705cfSriastradh#define KGEM_BUFFER_WRITE	0x1
82703b705cfSriastradh#define KGEM_BUFFER_INPLACE	0x2
82803b705cfSriastradh#define KGEM_BUFFER_LAST	0x4
82903b705cfSriastradh
83003b705cfSriastradh#define KGEM_BUFFER_WRITE_INPLACE (KGEM_BUFFER_WRITE | KGEM_BUFFER_INPLACE)
83103b705cfSriastradh
83203b705cfSriastradhstruct kgem_bo *kgem_create_buffer(struct kgem *kgem,
83303b705cfSriastradh				   uint32_t size, uint32_t flags,
83403b705cfSriastradh				   void **ret);
83503b705cfSriastradhstruct kgem_bo *kgem_create_buffer_2d(struct kgem *kgem,
83603b705cfSriastradh				      int width, int height, int bpp,
83703b705cfSriastradh				      uint32_t flags,
83803b705cfSriastradh				      void **ret);
83903b705cfSriastradhbool kgem_buffer_is_inplace(struct kgem_bo *bo);
84003b705cfSriastradhvoid kgem_buffer_read_sync(struct kgem *kgem, struct kgem_bo *bo);
84103b705cfSriastradh
84242542f5fSchristosint kgem_is_wedged(struct kgem *kgem);
84303b705cfSriastradhvoid kgem_throttle(struct kgem *kgem);
84403b705cfSriastradh#define MAX_INACTIVE_TIME 10
84503b705cfSriastradhbool kgem_expire_cache(struct kgem *kgem);
84642542f5fSchristosbool kgem_cleanup_cache(struct kgem *kgem);
84703b705cfSriastradh
84803b705cfSriastradhvoid kgem_clean_scanout_cache(struct kgem *kgem);
84903b705cfSriastradhvoid kgem_clean_large_cache(struct kgem *kgem);
85003b705cfSriastradh
85103b705cfSriastradh#if HAS_DEBUG_FULL
85203b705cfSriastradhvoid __kgem_batch_debug(struct kgem *kgem, uint32_t nbatch);
85303b705cfSriastradh#else
85403b705cfSriastradhstatic inline void __kgem_batch_debug(struct kgem *kgem, uint32_t nbatch)
85503b705cfSriastradh{
85603b705cfSriastradh	(void)kgem;
85703b705cfSriastradh	(void)nbatch;
85803b705cfSriastradh}
85903b705cfSriastradh#endif
86003b705cfSriastradh
86103b705cfSriastradhstatic inline void
86203b705cfSriastradhmemcpy_to_tiled_x(struct kgem *kgem,
86303b705cfSriastradh		  const void *src, void *dst, int bpp,
86403b705cfSriastradh		  int32_t src_stride, int32_t dst_stride,
86503b705cfSriastradh		  int16_t src_x, int16_t src_y,
86603b705cfSriastradh		  int16_t dst_x, int16_t dst_y,
86703b705cfSriastradh		  uint16_t width, uint16_t height)
86803b705cfSriastradh{
86942542f5fSchristos	assert(kgem->memcpy_to_tiled_x);
87042542f5fSchristos	assert(src_x >= 0 && src_y >= 0);
87142542f5fSchristos	assert(dst_x >= 0 && dst_y >= 0);
87242542f5fSchristos	assert(8*src_stride >= (src_x+width) * bpp);
87342542f5fSchristos	assert(8*dst_stride >= (dst_x+width) * bpp);
87403b705cfSriastradh	return kgem->memcpy_to_tiled_x(src, dst, bpp,
87503b705cfSriastradh				       src_stride, dst_stride,
87603b705cfSriastradh				       src_x, src_y,
87703b705cfSriastradh				       dst_x, dst_y,
87803b705cfSriastradh				       width, height);
87903b705cfSriastradh}
88003b705cfSriastradh
88103b705cfSriastradhstatic inline void
88203b705cfSriastradhmemcpy_from_tiled_x(struct kgem *kgem,
88303b705cfSriastradh		    const void *src, void *dst, int bpp,
88403b705cfSriastradh		    int32_t src_stride, int32_t dst_stride,
88503b705cfSriastradh		    int16_t src_x, int16_t src_y,
88603b705cfSriastradh		    int16_t dst_x, int16_t dst_y,
88703b705cfSriastradh		    uint16_t width, uint16_t height)
88803b705cfSriastradh{
88942542f5fSchristos	assert(kgem->memcpy_from_tiled_x);
89042542f5fSchristos	assert(src_x >= 0 && src_y >= 0);
89142542f5fSchristos	assert(dst_x >= 0 && dst_y >= 0);
89242542f5fSchristos	assert(8*src_stride >= (src_x+width) * bpp);
89342542f5fSchristos	assert(8*dst_stride >= (dst_x+width) * bpp);
89403b705cfSriastradh	return kgem->memcpy_from_tiled_x(src, dst, bpp,
89503b705cfSriastradh					 src_stride, dst_stride,
89603b705cfSriastradh					 src_x, src_y,
89703b705cfSriastradh					 dst_x, dst_y,
89803b705cfSriastradh					 width, height);
89903b705cfSriastradh}
90003b705cfSriastradh
901fe8aea9eSmrgvoid choose_memcpy_tiled_x(struct kgem *kgem, int swizzling, unsigned cpu);
90203b705cfSriastradh
90303b705cfSriastradh#endif /* KGEM_H */
904