aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.editorconfig19
-rw-r--r--.gitignore7
-rw-r--r--Android.common.mk12
-rw-r--r--Android.mk12
-rw-r--r--Makefile.am16
-rw-r--r--Makefile.sources5
-rw-r--r--README8
-rw-r--r--RELEASING26
-rw-r--r--amdgpu/Android.mk8
-rw-r--r--amdgpu/Makefile.sources1
-rwxr-xr-xamdgpu/amdgpu-symbol-check5
-rw-r--r--amdgpu/amdgpu.h79
-rw-r--r--amdgpu/amdgpu_asic_id.h165
-rw-r--r--amdgpu/amdgpu_bo.c14
-rw-r--r--amdgpu/amdgpu_cs.c181
-rw-r--r--amdgpu/amdgpu_device.c15
-rw-r--r--amdgpu/amdgpu_gpu_info.c22
-rw-r--r--amdgpu/amdgpu_internal.h16
-rw-r--r--amdgpu/libdrm_amdgpu.pc.in1
-rwxr-xr-xautogen.sh6
-rw-r--r--configure.ac88
-rw-r--r--etnaviv/Android.mk14
-rw-r--r--etnaviv/Makefile.am26
-rw-r--r--etnaviv/Makefile.sources12
-rwxr-xr-xetnaviv/etnaviv-symbol-check48
-rw-r--r--etnaviv/etnaviv_bo.c347
-rw-r--r--etnaviv/etnaviv_bo_cache.c196
-rw-r--r--etnaviv/etnaviv_cmd_stream.c243
-rw-r--r--etnaviv/etnaviv_device.c119
-rw-r--r--etnaviv/etnaviv_drm.h233
-rw-r--r--etnaviv/etnaviv_drmif.h191
-rw-r--r--etnaviv/etnaviv_gpu.c175
-rw-r--r--etnaviv/etnaviv_pipe.c83
-rw-r--r--etnaviv/etnaviv_priv.h201
-rw-r--r--etnaviv/libdrm_etnaviv.pc.in11
-rw-r--r--exynos/exynos_drm.c2
-rw-r--r--freedreno/Android.mk6
-rw-r--r--freedreno/Makefile.am2
-rw-r--r--freedreno/Makefile.sources1
-rwxr-xr-xfreedreno/freedreno-symbol-check6
-rw-r--r--freedreno/freedreno_bo.c148
-rw-r--r--freedreno/freedreno_bo_cache.c222
-rw-r--r--freedreno/freedreno_device.c62
-rw-r--r--freedreno/freedreno_drmif.h17
-rw-r--r--freedreno/freedreno_pipe.c4
-rw-r--r--freedreno/freedreno_priv.h42
-rw-r--r--freedreno/freedreno_ringbuffer.c71
-rw-r--r--freedreno/freedreno_ringbuffer.h27
-rw-r--r--freedreno/kgsl/README (renamed from freedreno/README)10
-rw-r--r--freedreno/kgsl/kgsl_bo.c6
-rw-r--r--freedreno/kgsl/kgsl_drm.h2
-rw-r--r--freedreno/kgsl/kgsl_pipe.c9
-rw-r--r--freedreno/kgsl/kgsl_ringbuffer.c19
-rw-r--r--freedreno/kgsl/msm_kgsl.h4
-rw-r--r--freedreno/msm/msm_bo.c20
-rw-r--r--freedreno/msm/msm_device.c3
-rw-r--r--freedreno/msm/msm_drm.h131
-rw-r--r--freedreno/msm/msm_pipe.c47
-rw-r--r--freedreno/msm/msm_priv.h17
-rw-r--r--freedreno/msm/msm_ringbuffer.c452
-rw-r--r--include/drm/README157
-rw-r--r--include/drm/amdgpu_drm.h44
-rw-r--r--include/drm/drm.h82
-rw-r--r--include/drm/drm_fourcc.h17
-rw-r--r--include/drm/drm_mode.h210
-rw-r--r--include/drm/drm_sarea.h2
-rw-r--r--include/drm/i915_drm.h315
-rw-r--r--include/drm/radeon_drm.h51
-rw-r--r--include/drm/vc4_drm.h302
-rw-r--r--include/drm/virtgpu_drm.h109
-rw-r--r--include/drm/vmwgfx_drm.h792
-rw-r--r--intel/Android.mk7
-rw-r--r--intel/Makefile.am1
-rw-r--r--intel/Makefile.sources3
-rwxr-xr-xintel/intel-symbol-check10
-rw-r--r--intel/intel_bufmgr.h20
-rw-r--r--intel/intel_bufmgr_fake.c6
-rw-r--r--intel/intel_bufmgr_gem.c541
-rw-r--r--intel/intel_chipset.h92
-rw-r--r--intel/intel_decode.c4
-rw-r--r--intel/tests/gen5-3d.batch-ref.txt2
-rw-r--r--intel/tests/gen6-3d.batch-ref.txt2
-rw-r--r--intel/uthash.h1074
-rw-r--r--libkms/Android.mk6
-rw-r--r--libkms/Makefile.am6
-rw-r--r--libkms/exynos.c3
-rw-r--r--libkms/libkms.pc.in1
-rw-r--r--libkms/linux.c99
-rw-r--r--libsync.h148
-rw-r--r--man/drm-kms.xml2
-rw-r--r--nouveau/Android.mk6
-rw-r--r--nouveau/Makefile.am2
-rw-r--r--radeon/Android.mk6
-rw-r--r--radeon/Makefile.am3
-rw-r--r--radeon/libdrm_radeon.pc.in1
-rw-r--r--radeon/radeon_bo_gem.c2
-rw-r--r--radeon/radeon_cs_gem.c12
-rw-r--r--radeon/radeon_surface.c16
-rw-r--r--tests/Makefile.am50
-rw-r--r--tests/amdgpu/amdgpu_test.c259
-rw-r--r--tests/amdgpu/amdgpu_test.h3
-rw-r--r--tests/amdgpu/basic_tests.c468
-rw-r--r--tests/amdgpu/bo_tests.c13
-rw-r--r--tests/amdgpu/cs_tests.c59
-rw-r--r--tests/amdgpu/vce_ib.h2
-rw-r--r--tests/amdgpu/vce_tests.c28
-rw-r--r--tests/auth.c138
-rw-r--r--tests/dristat.c285
-rw-r--r--tests/drmdevice.c71
-rw-r--r--tests/drmtest.c135
-rw-r--r--tests/drmtest.h40
-rw-r--r--tests/etnaviv/Makefile.am41
-rw-r--r--tests/etnaviv/cmdstream.xml.h242
-rw-r--r--tests/etnaviv/etnaviv_2d_test.c240
-rw-r--r--tests/etnaviv/etnaviv_bo_cache_test.c121
-rw-r--r--tests/etnaviv/etnaviv_cmd_stream_test.c123
-rw-r--r--tests/etnaviv/state.xml.h375
-rw-r--r--tests/etnaviv/state_2d.xml.h1497
-rw-r--r--tests/etnaviv/write_bmp.c151
-rw-r--r--tests/etnaviv/write_bmp.h (renamed from tests/getstats.c)52
-rw-r--r--tests/exynos/Makefile.am4
-rw-r--r--tests/getclient.c61
-rw-r--r--tests/getversion.c49
-rw-r--r--tests/kms/kms-steal-crtc.c4
-rw-r--r--tests/kms/kms-universal-planes.c5
-rw-r--r--tests/kmstest/Makefile.am6
-rw-r--r--tests/kmstest/main.c45
-rw-r--r--tests/lock.c264
-rw-r--r--tests/modetest/Android.mk3
-rw-r--r--tests/modetest/Makefile.am6
-rw-r--r--tests/modetest/modetest.c42
-rw-r--r--tests/name_from_fd.c58
-rw-r--r--tests/nouveau/Makefile.am8
-rw-r--r--tests/openclose.c37
-rw-r--r--tests/proptest/Android.mk3
-rw-r--r--tests/proptest/proptest.c4
-rw-r--r--tests/setversion.c91
-rw-r--r--tests/updatedraw.c154
-rw-r--r--tests/util/Android.mk7
-rw-r--r--tests/util/kms.c6
-rw-r--r--tests/vbltest/vbltest.c7
-rw-r--r--util_double_list.h8
-rw-r--r--vc4/Makefile.am34
-rw-r--r--vc4/Makefile.sources3
-rw-r--r--vc4/libdrm_vc4.pc.in9
-rw-r--r--vc4/vc4_packet.h397
-rw-r--r--vc4/vc4_qpu_defines.h274
-rw-r--r--xf86drm.c2433
-rw-r--r--xf86drm.h50
-rw-r--r--xf86drmMode.c52
-rw-r--r--xf86drmMode.h29
151 files changed, 13205 insertions, 3432 deletions
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 00000000..893b7be0
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,19 @@
1# To use this config with your editor, follow the instructions at:
2# http://editorconfig.org
3
4root = true
5
6[*]
7charset = utf-8
8insert_final_newline = true
9
10[*.{c,h}]
11indent_style = space
12indent_size = 4
13
14[{Makefile.*,*.mk}]
15indent_style = tab
16
17[*.m4]
18indent_style = space
19indent_size = 2
diff --git a/.gitignore b/.gitignore
index c1e87c50..d51e619b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -56,6 +56,8 @@ libdrm_omap.pc
56libdrm_exynos.pc 56libdrm_exynos.pc
57libdrm_freedreno.pc 57libdrm_freedreno.pc
58libdrm_amdgpu.pc 58libdrm_amdgpu.pc
59libdrm_vc4.pc
60libdrm_etnaviv.pc
59libkms.pc 61libkms.pc
60libtool 62libtool
61ltmain.sh 63ltmain.sh
@@ -92,10 +94,15 @@ tests/modeprint/modeprint
92tests/modetest/modetest 94tests/modetest/modetest
93tests/name_from_fd 95tests/name_from_fd
94tests/proptest/proptest 96tests/proptest/proptest
97tests/kms/kms-steal-crtc
98tests/kms/kms-universal-planes
95tests/kmstest/kmstest 99tests/kmstest/kmstest
96tests/vbltest/vbltest 100tests/vbltest/vbltest
97tests/radeon/radeon_ttm 101tests/radeon/radeon_ttm
98tests/exynos/exynos_fimg2d_event 102tests/exynos/exynos_fimg2d_event
99tests/exynos/exynos_fimg2d_perf 103tests/exynos/exynos_fimg2d_perf
100tests/exynos/exynos_fimg2d_test 104tests/exynos/exynos_fimg2d_test
105tests/etnaviv/etnaviv_2d_test
106tests/etnaviv/etnaviv_cmd_stream_test
107tests/etnaviv/etnaviv_bo_cache_test
101man/*.3 108man/*.3
diff --git a/Android.common.mk b/Android.common.mk
new file mode 100644
index 00000000..f57b8d37
--- /dev/null
+++ b/Android.common.mk
@@ -0,0 +1,12 @@
1# XXX: Consider moving these to config.h analogous to autoconf.
2LOCAL_CFLAGS += \
3 -DHAVE_VISIBILITY=1 \
4 -DHAVE_LIBDRM_ATOMIC_PRIMITIVES=1
5
6LOCAL_CFLAGS += \
7 -Wno-unused-parameter \
8 -Wno-missing-field-initializers
9
10# Quiet down the build system and remove any .h files from the sources
11LOCAL_SRC_FILES := $(patsubst %.h, , $(LOCAL_SRC_FILES))
12LOCAL_EXPORT_C_INCLUDE_DIRS += $(LOCAL_PATH)
diff --git a/Android.mk b/Android.mk
index 42d254cc..102c9a39 100644
--- a/Android.mk
+++ b/Android.mk
@@ -21,21 +21,21 @@
21# IN THE SOFTWARE. 21# IN THE SOFTWARE.
22# 22#
23 23
24
24ifneq ($(TARGET_USE_PRIVATE_LIBDRM),true) 25ifneq ($(TARGET_USE_PRIVATE_LIBDRM),true)
26
27LIBDRM_COMMON_MK := $(call my-dir)/Android.common.mk
28
25LOCAL_PATH := $(call my-dir) 29LOCAL_PATH := $(call my-dir)
26 30
27# Import variables LIBDRM_{,H_,INCLUDE_H_,INCLUDE_VMWGFX_H_}FILES 31# Import variables LIBDRM_{,H_,INCLUDE_H_,INCLUDE_VMWGFX_H_}FILES
28include $(LOCAL_PATH)/Makefile.sources 32include $(LOCAL_PATH)/Makefile.sources
29 33
30common_CFLAGS := \ 34common_CFLAGS := \
31 -DHAVE_VISIBILITY=1 \
32 -DHAVE_LIBDRM_ATOMIC_PRIMITIVES=1 \
33 -Wno-enum-conversion \ 35 -Wno-enum-conversion \
34 -Wno-missing-field-initializers \
35 -Wno-pointer-arith \ 36 -Wno-pointer-arith \
36 -Wno-sign-compare \ 37 -Wno-sign-compare \
37 -Wno-tautological-compare \ 38 -Wno-tautological-compare
38 -Wno-unused-parameter
39 39
40# Static library for the device (recovery) 40# Static library for the device (recovery)
41include $(CLEAR_VARS) 41include $(CLEAR_VARS)
@@ -53,6 +53,7 @@ LOCAL_C_INCLUDES := \
53LOCAL_CFLAGS := \ 53LOCAL_CFLAGS := \
54 $(common_CFLAGS) 54 $(common_CFLAGS)
55 55
56include $(LIBDRM_COMMON_MK)
56include $(BUILD_STATIC_LIBRARY) 57include $(BUILD_STATIC_LIBRARY)
57 58
58# Dynamic library for the device 59# Dynamic library for the device
@@ -72,6 +73,7 @@ LOCAL_C_INCLUDES := \
72LOCAL_CFLAGS := \ 73LOCAL_CFLAGS := \
73 $(common_CFLAGS) 74 $(common_CFLAGS)
74 75
76include $(LIBDRM_COMMON_MK)
75include $(BUILD_SHARED_LIBRARY) 77include $(BUILD_SHARED_LIBRARY)
76 78
77include $(call all-makefiles-under,$(LOCAL_PATH)) 79include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/Makefile.am b/Makefile.am
index 11ed1028..2bf644be 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -22,6 +22,7 @@ include Makefile.sources
22 22
23ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} 23ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
24 24
25AM_MAKEFLAGS = -s
25AM_DISTCHECK_CONFIGURE_FLAGS = \ 26AM_DISTCHECK_CONFIGURE_FLAGS = \
26 --enable-udev \ 27 --enable-udev \
27 --enable-libkms \ 28 --enable-libkms \
@@ -29,12 +30,14 @@ AM_DISTCHECK_CONFIGURE_FLAGS = \
29 --enable-radeon \ 30 --enable-radeon \
30 --enable-amdgpu \ 31 --enable-amdgpu \
31 --enable-nouveau \ 32 --enable-nouveau \
33 --enable-vc4 \
32 --enable-vmwgfx \ 34 --enable-vmwgfx \
33 --enable-omap-experimental-api \ 35 --enable-omap-experimental-api \
34 --enable-exynos-experimental-api \ 36 --enable-exynos-experimental-api \
35 --enable-freedreno \ 37 --enable-freedreno \
36 --enable-freedreno-kgsl\ 38 --enable-freedreno-kgsl\
37 --enable-tegra-experimental-api \ 39 --enable-tegra-experimental-api \
40 --enable-etnaviv-experimental-api \
38 --enable-install-test-programs \ 41 --enable-install-test-programs \
39 --enable-cairo-tests \ 42 --enable-cairo-tests \
40 --enable-manpages \ 43 --enable-manpages \
@@ -79,6 +82,14 @@ if HAVE_TEGRA
79TEGRA_SUBDIR = tegra 82TEGRA_SUBDIR = tegra
80endif 83endif
81 84
85if HAVE_VC4
86VC4_SUBDIR = vc4
87endif
88
89if HAVE_ETNAVIV
90ETNAVIV_SUBDIR = etnaviv
91endif
92
82if BUILD_MANPAGES 93if BUILD_MANPAGES
83if HAVE_MANPAGES_STYLESHEET 94if HAVE_MANPAGES_STYLESHEET
84MAN_SUBDIR = man 95MAN_SUBDIR = man
@@ -100,6 +111,8 @@ SUBDIRS = \
100 $(EXYNOS_SUBDIR) \ 111 $(EXYNOS_SUBDIR) \
101 $(FREEDRENO_SUBDIR) \ 112 $(FREEDRENO_SUBDIR) \
102 $(TEGRA_SUBDIR) \ 113 $(TEGRA_SUBDIR) \
114 $(VC4_SUBDIR) \
115 $(ETNAVIV_SUBDIR) \
103 tests \ 116 tests \
104 $(MAN_SUBDIR) \ 117 $(MAN_SUBDIR) \
105 $(ROCKCHIP_SUBDIR) 118 $(ROCKCHIP_SUBDIR)
@@ -119,8 +132,6 @@ libdrm_la_SOURCES = $(LIBDRM_FILES)
119libdrmincludedir = ${includedir} 132libdrmincludedir = ${includedir}
120libdrminclude_HEADERS = $(LIBDRM_H_FILES) 133libdrminclude_HEADERS = $(LIBDRM_H_FILES)
121 134
122EXTRA_DIST = Android.mk
123
124klibdrmincludedir = ${includedir}/libdrm 135klibdrmincludedir = ${includedir}/libdrm
125klibdrminclude_HEADERS = $(LIBDRM_INCLUDE_H_FILES) 136klibdrminclude_HEADERS = $(LIBDRM_INCLUDE_H_FILES)
126 137
@@ -128,6 +139,7 @@ if HAVE_VMWGFX
128klibdrminclude_HEADERS += $(LIBDRM_INCLUDE_VMWGFX_H_FILES) 139klibdrminclude_HEADERS += $(LIBDRM_INCLUDE_VMWGFX_H_FILES)
129endif 140endif
130 141
142EXTRA_DIST = include/drm/README
131 143
132copy-headers : 144copy-headers :
133 cp -r $(kernel_source)/include/uapi/drm/*.h $(top_srcdir)/include/drm/ 145 cp -r $(kernel_source)/include/uapi/drm/*.h $(top_srcdir)/include/drm/
diff --git a/Makefile.sources b/Makefile.sources
index a77f48de..10aa1d0f 100644
--- a/Makefile.sources
+++ b/Makefile.sources
@@ -13,6 +13,7 @@ LIBDRM_FILES := \
13 util_math.h 13 util_math.h
14 14
15LIBDRM_H_FILES := \ 15LIBDRM_H_FILES := \
16 libsync.h \
16 xf86drm.h \ 17 xf86drm.h \
17 xf86drmMode.h 18 xf86drmMode.h
18 19
@@ -32,7 +33,9 @@ LIBDRM_INCLUDE_H_FILES := \
32 include/drm/savage_drm.h \ 33 include/drm/savage_drm.h \
33 include/drm/sis_drm.h \ 34 include/drm/sis_drm.h \
34 include/drm/tegra_drm.h \ 35 include/drm/tegra_drm.h \
35 include/drm/via_drm.h 36 include/drm/vc4_drm.h \
37 include/drm/via_drm.h \
38 include/drm/virtgpu_drm.h
36 39
37LIBDRM_INCLUDE_VMWGFX_H_FILES := \ 40LIBDRM_INCLUDE_VMWGFX_H_FILES := \
38 include/drm/vmwgfx_drm.h 41 include/drm/vmwgfx_drm.h
diff --git a/README b/README
index 603a1c10..26cab9d3 100644
--- a/README
+++ b/README
@@ -1,7 +1,7 @@
1libdrm - userspace library for drm 1libdrm - userspace library for drm
2 2
3This is libdrm, a userspace library for accessing the DRM, direct 3This is libdrm, a userspace library for accessing the DRM, direct
4rendering manager, on Linux, BSD and other operating systes that 4rendering manager, on Linux, BSD and other operating systems that
5support the ioctl interface. The library provides wrapper functions 5support the ioctl interface. The library provides wrapper functions
6for the ioctls to avoid exposing the kernel interface directly, and 6for the ioctls to avoid exposing the kernel interface directly, and
7for chipsets with drm memory manager, support for tracking relocations 7for chipsets with drm memory manager, support for tracking relocations
@@ -15,7 +15,7 @@ with an older kernel.
15Compiling 15Compiling
16--------- 16---------
17 17
18libdrm is a standard autotools packages and follows the normal 18libdrm is a standard autotools package and follows the normal
19configure, build and install steps. The first step is to configure 19configure, build and install steps. The first step is to configure
20the package, which is done by running the configure shell script: 20the package, which is done by running the configure shell script:
21 21
@@ -37,5 +37,5 @@ and once make finishes successfully, install the package using
37 37
38 make install 38 make install
39 39
40If you are install into a system location, you will need to be root to 40If you are installing into a system location, you will need to be root
41perform the install step. 41to perform the install step.
diff --git a/RELEASING b/RELEASING
index 62c5be9f..262ca08d 100644
--- a/RELEASING
+++ b/RELEASING
@@ -9,21 +9,14 @@ However, this is up to whoever is driving the feature in question.
9 9
10Follow these steps to release a new version of libdrm: 10Follow these steps to release a new version of libdrm:
11 11
12 1) Ensure that there are no local, uncommitted/unpushed 12 1) Bump the version number in configure.ac. We seem to have settled
13 modifications. You're probably in a good state if both "git diff
14 HEAD" and "git log master..origin/master" give no output.
15
16 2) Bump the version number in configure.ac. We seem to have settled
17 for 2.4.x as the versioning scheme for libdrm, so just bump the 13 for 2.4.x as the versioning scheme for libdrm, so just bump the
18 micro version. 14 micro version.
19 15
20 3) Run autoconf and then re-run ./configure so the build system 16 2) Run autoconf and then re-run ./configure so the build system
21 picks up the new version number. 17 picks up the new version number.
22 18
23 4) (optional step, release.sh will make distcheck for you, but it can be 19 3) Verify that the code passes "make distcheck". Running "make
24 heart warming to verify that make distcheck passes)
25
26 Verify that the code passes "make distcheck". Running "make
27 distcheck" should result in no warnings or errors and end with a 20 distcheck" should result in no warnings or errors and end with a
28 message of the form: 21 message of the form:
29 22
@@ -36,20 +29,13 @@ Follow these steps to release a new version of libdrm:
36 Make sure that the version number reported by distcheck and in 29 Make sure that the version number reported by distcheck and in
37 the tarball names matches the number you bumped to in configure.ac. 30 the tarball names matches the number you bumped to in configure.ac.
38 31
39 5) Commit the configure.ac change and make an annotated tag for that 32 4) Push the updated master branch with the bumped version number:
40 commit with the version number of the release as the name and a
41 message of "libdrm X.Y.Z". For example, for the 2.4.16 release
42 the command is:
43
44 git tag -a 2.4.16 -m "libdrm 2.4.16"
45
46 6) Push the commit and tag by saying
47 33
48 git push --tags origin master 34 git push origin master
49 35
50 assuming the remote for the upstream libdrm repo is called origin. 36 assuming the remote for the upstream libdrm repo is called origin.
51 37
52 7) Use the release.sh script from the xorg/util/modular repo to 38 5) Use the release.sh script from the xorg/util/modular repo to
53 upload the tarballs to the freedesktop.org download area and 39 upload the tarballs to the freedesktop.org download area and
54 create an announce email template. The script takes one argument: 40 create an announce email template. The script takes one argument:
55 the path to the libdrm checkout. So, if a checkout of modular is 41 the path to the libdrm checkout. So, if a checkout of modular is
diff --git a/amdgpu/Android.mk b/amdgpu/Android.mk
index e5777e53..bf0611ba 100644
--- a/amdgpu/Android.mk
+++ b/amdgpu/Android.mk
@@ -5,14 +5,10 @@ include $(CLEAR_VARS)
5include $(LOCAL_PATH)/Makefile.sources 5include $(LOCAL_PATH)/Makefile.sources
6 6
7LOCAL_MODULE := libdrm_amdgpu 7LOCAL_MODULE := libdrm_amdgpu
8LOCAL_MODULE_TAGS := optional
9 8
10LOCAL_SHARED_LIBRARIES := libdrm 9LOCAL_SHARED_LIBRARIES := libdrm
11 10
12LOCAL_SRC_FILES := $(filter-out %.h,$(LIBDRM_AMDGPU_FILES)) 11LOCAL_SRC_FILES := $(LIBDRM_AMDGPU_FILES)
13LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
14
15LOCAL_CFLAGS := \
16 -DHAVE_LIBDRM_ATOMIC_PRIMITIVES=1
17 12
13include $(LIBDRM_COMMON_MK)
18include $(BUILD_SHARED_LIBRARY) 14include $(BUILD_SHARED_LIBRARY)
diff --git a/amdgpu/Makefile.sources b/amdgpu/Makefile.sources
index 0c0b9a93..487b9e0a 100644
--- a/amdgpu/Makefile.sources
+++ b/amdgpu/Makefile.sources
@@ -1,4 +1,5 @@
1LIBDRM_AMDGPU_FILES := \ 1LIBDRM_AMDGPU_FILES := \
2 amdgpu_asic_id.h \
2 amdgpu_bo.c \ 3 amdgpu_bo.c \
3 amdgpu_cs.c \ 4 amdgpu_cs.c \
4 amdgpu_device.c \ 5 amdgpu_device.c \
diff --git a/amdgpu/amdgpu-symbol-check b/amdgpu/amdgpu-symbol-check
index 9a0b36cb..87f4fd2c 100755
--- a/amdgpu/amdgpu-symbol-check
+++ b/amdgpu/amdgpu-symbol-check
@@ -24,13 +24,18 @@ amdgpu_bo_set_metadata
24amdgpu_bo_va_op 24amdgpu_bo_va_op
25amdgpu_bo_wait_for_idle 25amdgpu_bo_wait_for_idle
26amdgpu_create_bo_from_user_mem 26amdgpu_create_bo_from_user_mem
27amdgpu_cs_create_semaphore
27amdgpu_cs_ctx_create 28amdgpu_cs_ctx_create
28amdgpu_cs_ctx_free 29amdgpu_cs_ctx_free
30amdgpu_cs_destroy_semaphore
29amdgpu_cs_query_fence_status 31amdgpu_cs_query_fence_status
30amdgpu_cs_query_reset_state 32amdgpu_cs_query_reset_state
33amdgpu_cs_signal_semaphore
31amdgpu_cs_submit 34amdgpu_cs_submit
35amdgpu_cs_wait_semaphore
32amdgpu_device_deinitialize 36amdgpu_device_deinitialize
33amdgpu_device_initialize 37amdgpu_device_initialize
38amdgpu_get_marketing_name
34amdgpu_query_buffer_size_alignment 39amdgpu_query_buffer_size_alignment
35amdgpu_query_crtc_from_id 40amdgpu_query_crtc_from_id
36amdgpu_query_firmware_version 41amdgpu_query_firmware_version
diff --git a/amdgpu/amdgpu.h b/amdgpu/amdgpu.h
index e44d802b..7b26a04c 100644
--- a/amdgpu/amdgpu.h
+++ b/amdgpu/amdgpu.h
@@ -124,6 +124,11 @@ typedef struct amdgpu_bo_list *amdgpu_bo_list_handle;
124 */ 124 */
125typedef struct amdgpu_va *amdgpu_va_handle; 125typedef struct amdgpu_va *amdgpu_va_handle;
126 126
127/**
128 * Define handle for semaphore
129 */
130typedef struct amdgpu_semaphore *amdgpu_semaphore_handle;
131
127/*--------------------------------------------------------------------------*/ 132/*--------------------------------------------------------------------------*/
128/* -------------------------- Structures ---------------------------------- */ 133/* -------------------------- Structures ---------------------------------- */
129/*--------------------------------------------------------------------------*/ 134/*--------------------------------------------------------------------------*/
@@ -680,7 +685,7 @@ int amdgpu_create_bo_from_user_mem(amdgpu_device_handle dev,
680int amdgpu_bo_free(amdgpu_bo_handle buf_handle); 685int amdgpu_bo_free(amdgpu_bo_handle buf_handle);
681 686
682/** 687/**
683 * Request CPU access to GPU accessable memory 688 * Request CPU access to GPU accessible memory
684 * 689 *
685 * \param buf_handle - \c [in] Buffer handle 690 * \param buf_handle - \c [in] Buffer handle
686 * \param cpu - \c [out] CPU address to be used for access 691 * \param cpu - \c [out] CPU address to be used for access
@@ -846,7 +851,7 @@ int amdgpu_cs_query_reset_state(amdgpu_context_handle context,
846 * order. 851 * order.
847 * 852 *
848 * The caller can specify the user fence buffer/location with the fence_info in the 853 * The caller can specify the user fence buffer/location with the fence_info in the
849 * cs_request.The sequence number is returned via the 'seq_no' paramter 854 * cs_request.The sequence number is returned via the 'seq_no' parameter
850 * in ibs_request structure. 855 * in ibs_request structure.
851 * 856 *
852 * 857 *
@@ -1180,4 +1185,74 @@ int amdgpu_bo_va_op(amdgpu_bo_handle bo,
1180 uint64_t flags, 1185 uint64_t flags,
1181 uint32_t ops); 1186 uint32_t ops);
1182 1187
1188/**
1189 * create semaphore
1190 *
1191 * \param sem - \c [out] semaphore handle
1192 *
1193 * \return 0 on success\n
1194 * <0 - Negative POSIX Error code
1195 *
1196*/
1197int amdgpu_cs_create_semaphore(amdgpu_semaphore_handle *sem);
1198
1199/**
1200 * signal semaphore
1201 *
1202 * \param context - \c [in] GPU Context
1203 * \param ip_type - \c [in] Hardware IP block type = AMDGPU_HW_IP_*
1204 * \param ip_instance - \c [in] Index of the IP block of the same type
1205 * \param ring - \c [in] Specify ring index of the IP
1206 * \param sem - \c [in] semaphore handle
1207 *
1208 * \return 0 on success\n
1209 * <0 - Negative POSIX Error code
1210 *
1211*/
1212int amdgpu_cs_signal_semaphore(amdgpu_context_handle ctx,
1213 uint32_t ip_type,
1214 uint32_t ip_instance,
1215 uint32_t ring,
1216 amdgpu_semaphore_handle sem);
1217
1218/**
1219 * wait semaphore
1220 *
1221 * \param context - \c [in] GPU Context
1222 * \param ip_type - \c [in] Hardware IP block type = AMDGPU_HW_IP_*
1223 * \param ip_instance - \c [in] Index of the IP block of the same type
1224 * \param ring - \c [in] Specify ring index of the IP
1225 * \param sem - \c [in] semaphore handle
1226 *
1227 * \return 0 on success\n
1228 * <0 - Negative POSIX Error code
1229 *
1230*/
1231int amdgpu_cs_wait_semaphore(amdgpu_context_handle ctx,
1232 uint32_t ip_type,
1233 uint32_t ip_instance,
1234 uint32_t ring,
1235 amdgpu_semaphore_handle sem);
1236
1237/**
1238 * destroy semaphore
1239 *
1240 * \param sem - \c [in] semaphore handle
1241 *
1242 * \return 0 on success\n
1243 * <0 - Negative POSIX Error code
1244 *
1245*/
1246int amdgpu_cs_destroy_semaphore(amdgpu_semaphore_handle sem);
1247
1248/**
1249 * Get the ASIC marketing name
1250 *
1251 * \param dev - \c [in] Device handle. See #amdgpu_device_initialize()
1252 *
1253 * \return the constant string of the marketing name
1254 * "NULL" means the ASIC is not found
1255*/
1256const char *amdgpu_get_marketing_name(amdgpu_device_handle dev);
1257
1183#endif /* #ifdef _AMDGPU_H_ */ 1258#endif /* #ifdef _AMDGPU_H_ */
diff --git a/amdgpu/amdgpu_asic_id.h b/amdgpu/amdgpu_asic_id.h
new file mode 100644
index 00000000..3e7d736b
--- /dev/null
+++ b/amdgpu/amdgpu_asic_id.h
@@ -0,0 +1,165 @@
1/*
2 * Copyright © 2016 Advanced Micro Devices, Inc.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21 * OTHER DEALINGS IN THE SOFTWARE.
22 *
23 */
24
25#ifndef __AMDGPU_ASIC_ID_H__
26#define __AMDGPU_ASIC_ID_H__
27
28static struct amdgpu_asic_id_table_t {
29 uint32_t did;
30 uint32_t rid;
31 const char *marketing_name;
32} const amdgpu_asic_id_table [] = {
33 {0x6600, 0x0, "AMD Radeon HD 8600/8700M"},
34 {0x6600, 0x81, "AMD Radeon R7 M370"},
35 {0x6601, 0x0, "AMD Radeon HD 8500M/8700M"},
36 {0x6604, 0x0, "AMD Radeon R7 M265 Series"},
37 {0x6604, 0x81, "AMD Radeon R7 M350"},
38 {0x6605, 0x0, "AMD Radeon R7 M260 Series"},
39 {0x6605, 0x81, "AMD Radeon R7 M340"},
40 {0x6606, 0x0, "AMD Radeon HD 8790M"},
41 {0x6607, 0x0, "AMD Radeon HD8530M"},
42 {0x6608, 0x0, "AMD FirePro W2100"},
43 {0x6610, 0x0, "AMD Radeon HD 8600 Series"},
44 {0x6610, 0x81, "AMD Radeon R7 350"},
45 {0x6610, 0x83, "AMD Radeon R5 340"},
46 {0x6611, 0x0, "AMD Radeon HD 8500 Series"},
47 {0x6613, 0x0, "AMD Radeon HD 8500 series"},
48 {0x6617, 0xC7, "AMD Radeon R7 240 Series"},
49 {0x6640, 0x0, "AMD Radeon HD 8950"},
50 {0x6640, 0x80, "AMD Radeon R9 M380"},
51 {0x6646, 0x0, "AMD Radeon R9 M280X"},
52 {0x6646, 0x80, "AMD Radeon R9 M470X"},
53 {0x6647, 0x0, "AMD Radeon R9 M270X"},
54 {0x6647, 0x80, "AMD Radeon R9 M380"},
55 {0x6649, 0x0, "AMD FirePro W5100"},
56 {0x6658, 0x0, "AMD Radeon R7 200 Series"},
57 {0x665C, 0x0, "AMD Radeon HD 7700 Series"},
58 {0x665D, 0x0, "AMD Radeon R7 200 Series"},
59 {0x665F, 0x81, "AMD Radeon R7 300 Series"},
60 {0x6660, 0x0, "AMD Radeon HD 8600M Series"},
61 {0x6660, 0x81, "AMD Radeon R5 M335"},
62 {0x6660, 0x83, "AMD Radeon R5 M330"},
63 {0x6663, 0x0, "AMD Radeon HD 8500M Series"},
64 {0x6663, 0x83, "AMD Radeon R5 M320"},
65 {0x6664, 0x0, "AMD Radeon R5 M200 Series"},
66 {0x6665, 0x0, "AMD Radeon R5 M200 Series"},
67 {0x6665, 0x83, "AMD Radeon R5 M320"},
68 {0x6667, 0x0, "AMD Radeon R5 M200 Series"},
69 {0x666F, 0x0, "AMD Radeon HD 8500M"},
70 {0x6780, 0x0, "ATI FirePro V (FireGL V) Graphics Adapter"},
71 {0x678A, 0x0, "ATI FirePro V (FireGL V) Graphics Adapter"},
72 {0x6798, 0x0, "AMD Radeon HD 7900 Series"},
73 {0x679A, 0x0, "AMD Radeon HD 7900 Series"},
74 {0x679B, 0x0, "AMD Radeon HD 7900 Series"},
75 {0x679E, 0x0, "AMD Radeon HD 7800 Series"},
76 {0x67A0, 0x0, "HAWAII XTGL (67A0)"},
77 {0x67A1, 0x0, "HAWAII GL40 (67A1)"},
78 {0x67B0, 0x0, "AMD Radeon R9 200 Series"},
79 {0x67B0, 0x80, "AMD Radeon R9 390 Series"},
80 {0x67B1, 0x0, "AMD Radeon R9 200 Series"},
81 {0x67B1, 0x80, "AMD Radeon R9 390 Series"},
82 {0x67B9, 0x0, "AMD Radeon R9 200 Series"},
83 {0x67DF, 0xC4, "AMD Radeon RX 480 Graphics"},
84 {0x67DF, 0xC5, "AMD Radeon RX 470 Graphics"},
85 {0x67DF, 0xC7, "AMD Radeon RX 480 Graphics"},
86 {0x67DF, 0xCF, "AMD Radeon RX 470 Graphics"},
87 {0x67C4, 0x00, "AMD Radeon Pro WX 7100 Graphics"},
88 {0x67C7, 0x00, "AMD Radeon Pro WX 5100 Graphics"},
89 {0x67C0, 0x00, "AMD Radeon Pro WX 7100 Graphics"},
90 {0x67E0, 0x00, "AMD Radeon Pro WX Series Graphics"},
91 {0x67E3, 0x00, "AMD Radeon Pro WX 4100 Graphics"},
92 {0x67E8, 0x00, "AMD Radeon Pro WX Series Graphics"},
93 {0x67E8, 0x01, "AMD Radeon Pro WX Series Graphics"},
94 {0x67E8, 0x80, "AMD Radeon E9260 Graphics"},
95 {0x67EB, 0x00, "AMD Radeon Pro WX Series Graphics"},
96 {0x67EF, 0xC0, "AMD Radeon RX Graphics"},
97 {0x67EF, 0xC1, "AMD Radeon RX 460 Graphics"},
98 {0x67EF, 0xC5, "AMD Radeon RX 460 Graphics"},
99 {0x67EF, 0xC7, "AMD Radeon RX Graphics"},
100 {0x67EF, 0xCF, "AMD Radeon RX 460 Graphics"},
101 {0x67EF, 0xEF, "AMD Radeon RX Graphics"},
102 {0x67FF, 0xC0, "AMD Radeon RX Graphics"},
103 {0x67FF, 0xC1, "AMD Radeon RX Graphics"},
104 {0x6800, 0x0, "AMD Radeon HD 7970M"},
105 {0x6801, 0x0, "AMD Radeon(TM) HD8970M"},
106 {0x6808, 0x0, "ATI FirePro V(FireGL V) Graphics Adapter"},
107 {0x6809, 0x0, "ATI FirePro V(FireGL V) Graphics Adapter"},
108 {0x6810, 0x0, "AMD Radeon(TM) HD 8800 Series"},
109 {0x6810, 0x81, "AMD Radeon R7 370 Series"},
110 {0x6811, 0x0, "AMD Radeon(TM) HD8800 Series"},
111 {0x6811, 0x81, "AMD Radeon R7 300 Series"},
112 {0x6818, 0x0, "AMD Radeon HD 7800 Series"},
113 {0x6819, 0x0, "AMD Radeon HD 7800 Series"},
114 {0x6820, 0x0, "AMD Radeon HD 8800M Series"},
115 {0x6820, 0x81, "AMD Radeon R9 M375"},
116 {0x6820, 0x83, "AMD Radeon R9 M375X"},
117 {0x6821, 0x0, "AMD Radeon HD 8800M Series"},
118 {0x6821, 0x87, "AMD Radeon R7 M380"},
119 {0x6821, 0x83, "AMD Radeon R9 M370X"},
120 {0x6822, 0x0, "AMD Radeon E8860"},
121 {0x6823, 0x0, "AMD Radeon HD 8800M Series"},
122 {0x6825, 0x0, "AMD Radeon HD 7800M Series"},
123 {0x6827, 0x0, "AMD Radeon HD 7800M Series"},
124 {0x6828, 0x0, "ATI FirePro V(FireGL V) Graphics Adapter"},
125 {0x682B, 0x0, "AMD Radeon HD 8800M Series"},
126 {0x682B, 0x87, "AMD Radeon R9 M360"},
127 {0x682C, 0x0, "AMD FirePro W4100"},
128 {0x682D, 0x0, "AMD Radeon HD 7700M Series"},
129 {0x682F, 0x0, "AMD Radeon HD 7700M Series"},
130 {0x6835, 0x0, "AMD Radeon R7 Series / HD 9000 Series"},
131 {0x6837, 0x0, "AMD Radeon HD7700 Series"},
132 {0x683D, 0x0, "AMD Radeon HD 7700 Series"},
133 {0x683F, 0x0, "AMD Radeon HD 7700 Series"},
134 {0x6900, 0x0, "AMD Radeon R7 M260"},
135 {0x6900, 0x81, "AMD Radeon R7 M360"},
136 {0x6900, 0x83, "AMD Radeon R7 M340"},
137 {0x6901, 0x0, "AMD Radeon R5 M255"},
138 {0x6907, 0x0, "AMD Radeon R5 M255"},
139 {0x6907, 0x87, "AMD Radeon R5 M315"},
140 {0x6920, 0x0, "AMD Radeon R9 M395X"},
141 {0x6920, 0x1, "AMD Radeon R9 M390X"},
142 {0x6921, 0x0, "AMD Radeon R9 M295X"},
143 {0x6929, 0x0, "AMD FirePro S7150"},
144 {0x692B, 0x0, "AMD FirePro W7100"},
145 {0x6938, 0x0, "AMD Radeon R9 200 Series"},
146 {0x6938, 0xF0, "AMD Radeon R9 200 Series"},
147 {0x6938, 0xF1, "AMD Radeon R9 380 Series"},
148 {0x6939, 0xF0, "AMD Radeon R9 200 Series"},
149 {0x6939, 0x0, "AMD Radeon R9 200 Series"},
150 {0x6939, 0xF1, "AMD Radeon R9 380 Series"},
151 {0x7300, 0xC8, "AMD Radeon R9 Fury Series"},
152 {0x7300, 0xCB, "AMD Radeon R9 Fury Series"},
153 {0x7300, 0xCA, "AMD Radeon R9 Fury Series"},
154 {0x9874, 0xC4, "AMD Radeon R7 Graphics"},
155 {0x9874, 0xC5, "AMD Radeon R6 Graphics"},
156 {0x9874, 0xC6, "AMD Radeon R6 Graphics"},
157 {0x9874, 0xC7, "AMD Radeon R5 Graphics"},
158 {0x9874, 0x81, "AMD Radeon R6 Graphics"},
159 {0x9874, 0x87, "AMD Radeon R5 Graphics"},
160 {0x9874, 0x85, "AMD Radeon R6 Graphics"},
161 {0x9874, 0x84, "AMD Radeon R7 Graphics"},
162
163 {0x0000, 0x0, "\0"},
164};
165#endif
diff --git a/amdgpu/amdgpu_bo.c b/amdgpu/amdgpu_bo.c
index 1a5a4011..d30fd1e7 100644
--- a/amdgpu/amdgpu_bo.c
+++ b/amdgpu/amdgpu_bo.c
@@ -537,18 +537,10 @@ int amdgpu_create_bo_from_user_mem(amdgpu_device_handle dev,
537 int r; 537 int r;
538 struct amdgpu_bo *bo; 538 struct amdgpu_bo *bo;
539 struct drm_amdgpu_gem_userptr args; 539 struct drm_amdgpu_gem_userptr args;
540 uintptr_t cpu0;
541 uint32_t ps, off;
542 540
543 memset(&args, 0, sizeof(args)); 541 args.addr = (uintptr_t)cpu;
544 ps = getpagesize(); 542 args.flags = AMDGPU_GEM_USERPTR_ANONONLY | AMDGPU_GEM_USERPTR_REGISTER |
545 543 AMDGPU_GEM_USERPTR_VALIDATE;
546 cpu0 = ROUND_DOWN((uintptr_t)cpu, ps);
547 off = (uintptr_t)cpu - cpu0;
548 size = ROUND_UP(size + off, ps);
549
550 args.addr = cpu0;
551 args.flags = AMDGPU_GEM_USERPTR_ANONONLY | AMDGPU_GEM_USERPTR_REGISTER;
552 args.size = size; 544 args.size = size;
553 r = drmCommandWriteRead(dev->fd, DRM_AMDGPU_GEM_USERPTR, 545 r = drmCommandWriteRead(dev->fd, DRM_AMDGPU_GEM_USERPTR,
554 &args, sizeof(args)); 546 &args, sizeof(args));
diff --git a/amdgpu/amdgpu_cs.c b/amdgpu/amdgpu_cs.c
index 6747158c..fb5b3a8c 100644
--- a/amdgpu/amdgpu_cs.c
+++ b/amdgpu/amdgpu_cs.c
@@ -40,6 +40,9 @@
40#include "amdgpu_drm.h" 40#include "amdgpu_drm.h"
41#include "amdgpu_internal.h" 41#include "amdgpu_internal.h"
42 42
43static int amdgpu_cs_unreference_sem(amdgpu_semaphore_handle sem);
44static int amdgpu_cs_reset_sem(amdgpu_semaphore_handle sem);
45
43/** 46/**
44 * Create command submission context 47 * Create command submission context
45 * 48 *
@@ -53,6 +56,7 @@ int amdgpu_cs_ctx_create(amdgpu_device_handle dev,
53{ 56{
54 struct amdgpu_context *gpu_context; 57 struct amdgpu_context *gpu_context;
55 union drm_amdgpu_ctx args; 58 union drm_amdgpu_ctx args;
59 int i, j, k;
56 int r; 60 int r;
57 61
58 if (NULL == dev) 62 if (NULL == dev)
@@ -66,6 +70,10 @@ int amdgpu_cs_ctx_create(amdgpu_device_handle dev,
66 70
67 gpu_context->dev = dev; 71 gpu_context->dev = dev;
68 72
73 r = pthread_mutex_init(&gpu_context->sequence_mutex, NULL);
74 if (r)
75 goto error;
76
69 /* Create the context */ 77 /* Create the context */
70 memset(&args, 0, sizeof(args)); 78 memset(&args, 0, sizeof(args));
71 args.in.op = AMDGPU_CTX_OP_ALLOC_CTX; 79 args.in.op = AMDGPU_CTX_OP_ALLOC_CTX;
@@ -74,11 +82,16 @@ int amdgpu_cs_ctx_create(amdgpu_device_handle dev,
74 goto error; 82 goto error;
75 83
76 gpu_context->id = args.out.alloc.ctx_id; 84 gpu_context->id = args.out.alloc.ctx_id;
85 for (i = 0; i < AMDGPU_HW_IP_NUM; i++)
86 for (j = 0; j < AMDGPU_HW_IP_INSTANCE_MAX_COUNT; j++)
87 for (k = 0; k < AMDGPU_CS_MAX_RINGS; k++)
88 list_inithead(&gpu_context->sem_list[i][j][k]);
77 *context = (amdgpu_context_handle)gpu_context; 89 *context = (amdgpu_context_handle)gpu_context;
78 90
79 return 0; 91 return 0;
80 92
81error: 93error:
94 pthread_mutex_destroy(&gpu_context->sequence_mutex);
82 free(gpu_context); 95 free(gpu_context);
83 return r; 96 return r;
84} 97}
@@ -94,18 +107,32 @@ error:
94int amdgpu_cs_ctx_free(amdgpu_context_handle context) 107int amdgpu_cs_ctx_free(amdgpu_context_handle context)
95{ 108{
96 union drm_amdgpu_ctx args; 109 union drm_amdgpu_ctx args;
110 int i, j, k;
97 int r; 111 int r;
98 112
99 if (NULL == context) 113 if (NULL == context)
100 return -EINVAL; 114 return -EINVAL;
101 115
116 pthread_mutex_destroy(&context->sequence_mutex);
117
102 /* now deal with kernel side */ 118 /* now deal with kernel side */
103 memset(&args, 0, sizeof(args)); 119 memset(&args, 0, sizeof(args));
104 args.in.op = AMDGPU_CTX_OP_FREE_CTX; 120 args.in.op = AMDGPU_CTX_OP_FREE_CTX;
105 args.in.ctx_id = context->id; 121 args.in.ctx_id = context->id;
106 r = drmCommandWriteRead(context->dev->fd, DRM_AMDGPU_CTX, 122 r = drmCommandWriteRead(context->dev->fd, DRM_AMDGPU_CTX,
107 &args, sizeof(args)); 123 &args, sizeof(args));
108 124 for (i = 0; i < AMDGPU_HW_IP_NUM; i++) {
125 for (j = 0; j < AMDGPU_HW_IP_INSTANCE_MAX_COUNT; j++) {
126 for (k = 0; k < AMDGPU_CS_MAX_RINGS; k++) {
127 amdgpu_semaphore_handle sem;
128 LIST_FOR_EACH_ENTRY(sem, &context->sem_list[i][j][k], list) {
129 list_del(&sem->list);
130 amdgpu_cs_reset_sem(sem);
131 amdgpu_cs_unreference_sem(sem);
132 }
133 }
134 }
135 }
109 free(context); 136 free(context);
110 137
111 return r; 138 return r;
@@ -150,7 +177,10 @@ static int amdgpu_cs_submit_one(amdgpu_context_handle context,
150 struct drm_amdgpu_cs_chunk *chunks; 177 struct drm_amdgpu_cs_chunk *chunks;
151 struct drm_amdgpu_cs_chunk_data *chunk_data; 178 struct drm_amdgpu_cs_chunk_data *chunk_data;
152 struct drm_amdgpu_cs_chunk_dep *dependencies = NULL; 179 struct drm_amdgpu_cs_chunk_dep *dependencies = NULL;
153 uint32_t i, size; 180 struct drm_amdgpu_cs_chunk_dep *sem_dependencies = NULL;
181 struct list_head *sem_list;
182 amdgpu_semaphore_handle sem, tmp;
183 uint32_t i, size, sem_count = 0;
154 bool user_fence; 184 bool user_fence;
155 int r = 0; 185 int r = 0;
156 186
@@ -160,9 +190,13 @@ static int amdgpu_cs_submit_one(amdgpu_context_handle context,
160 return -EINVAL; 190 return -EINVAL;
161 if (ibs_request->number_of_ibs > AMDGPU_CS_MAX_IBS_PER_SUBMIT) 191 if (ibs_request->number_of_ibs > AMDGPU_CS_MAX_IBS_PER_SUBMIT)
162 return -EINVAL; 192 return -EINVAL;
193 if (ibs_request->number_of_ibs == 0) {
194 ibs_request->seq_no = AMDGPU_NULL_SUBMIT_SEQ;
195 return 0;
196 }
163 user_fence = (ibs_request->fence_info.handle != NULL); 197 user_fence = (ibs_request->fence_info.handle != NULL);
164 198
165 size = ibs_request->number_of_ibs + (user_fence ? 2 : 1); 199 size = ibs_request->number_of_ibs + (user_fence ? 2 : 1) + 1;
166 200
167 chunk_array = alloca(sizeof(uint64_t) * size); 201 chunk_array = alloca(sizeof(uint64_t) * size);
168 chunks = alloca(sizeof(struct drm_amdgpu_cs_chunk) * size); 202 chunks = alloca(sizeof(struct drm_amdgpu_cs_chunk) * size);
@@ -196,6 +230,8 @@ static int amdgpu_cs_submit_one(amdgpu_context_handle context,
196 chunk_data[i].ib_data.flags = ib->flags; 230 chunk_data[i].ib_data.flags = ib->flags;
197 } 231 }
198 232
233 pthread_mutex_lock(&context->sequence_mutex);
234
199 if (user_fence) { 235 if (user_fence) {
200 i = cs.in.num_chunks++; 236 i = cs.in.num_chunks++;
201 237
@@ -240,15 +276,49 @@ static int amdgpu_cs_submit_one(amdgpu_context_handle context,
240 chunks[i].chunk_data = (uint64_t)(uintptr_t)dependencies; 276 chunks[i].chunk_data = (uint64_t)(uintptr_t)dependencies;
241 } 277 }
242 278
279 sem_list = &context->sem_list[ibs_request->ip_type][ibs_request->ip_instance][ibs_request->ring];
280 LIST_FOR_EACH_ENTRY(sem, sem_list, list)
281 sem_count++;
282 if (sem_count) {
283 sem_dependencies = malloc(sizeof(struct drm_amdgpu_cs_chunk_dep) * sem_count);
284 if (!sem_dependencies) {
285 r = -ENOMEM;
286 goto error_unlock;
287 }
288 sem_count = 0;
289 LIST_FOR_EACH_ENTRY_SAFE(sem, tmp, sem_list, list) {
290 struct amdgpu_cs_fence *info = &sem->signal_fence;
291 struct drm_amdgpu_cs_chunk_dep *dep = &sem_dependencies[sem_count++];
292 dep->ip_type = info->ip_type;
293 dep->ip_instance = info->ip_instance;
294 dep->ring = info->ring;
295 dep->ctx_id = info->context->id;
296 dep->handle = info->fence;
297
298 list_del(&sem->list);
299 amdgpu_cs_reset_sem(sem);
300 amdgpu_cs_unreference_sem(sem);
301 }
302 i = cs.in.num_chunks++;
303
304 /* dependencies chunk */
305 chunk_array[i] = (uint64_t)(uintptr_t)&chunks[i];
306 chunks[i].chunk_id = AMDGPU_CHUNK_ID_DEPENDENCIES;
307 chunks[i].length_dw = sizeof(struct drm_amdgpu_cs_chunk_dep) / 4 * sem_count;
308 chunks[i].chunk_data = (uint64_t)(uintptr_t)sem_dependencies;
309 }
310
243 r = drmCommandWriteRead(context->dev->fd, DRM_AMDGPU_CS, 311 r = drmCommandWriteRead(context->dev->fd, DRM_AMDGPU_CS,
244 &cs, sizeof(cs)); 312 &cs, sizeof(cs));
245 if (r) 313 if (r)
246 goto error_unlock; 314 goto error_unlock;
247 315
248 ibs_request->seq_no = cs.out.handle; 316 ibs_request->seq_no = cs.out.handle;
249 317 context->last_seq[ibs_request->ip_type][ibs_request->ip_instance][ibs_request->ring] = ibs_request->seq_no;
250error_unlock: 318error_unlock:
319 pthread_mutex_unlock(&context->sequence_mutex);
251 free(dependencies); 320 free(dependencies);
321 free(sem_dependencies);
252 return r; 322 return r;
253} 323}
254 324
@@ -356,6 +426,10 @@ int amdgpu_cs_query_fence_status(struct amdgpu_cs_fence *fence,
356 return -EINVAL; 426 return -EINVAL;
357 if (fence->ring >= AMDGPU_CS_MAX_RINGS) 427 if (fence->ring >= AMDGPU_CS_MAX_RINGS)
358 return -EINVAL; 428 return -EINVAL;
429 if (fence->fence == AMDGPU_NULL_SUBMIT_SEQ) {
430 *expired = true;
431 return 0;
432 }
359 433
360 *expired = false; 434 *expired = false;
361 435
@@ -369,3 +443,102 @@ int amdgpu_cs_query_fence_status(struct amdgpu_cs_fence *fence,
369 return r; 443 return r;
370} 444}
371 445
446int amdgpu_cs_create_semaphore(amdgpu_semaphore_handle *sem)
447{
448 struct amdgpu_semaphore *gpu_semaphore;
449
450 if (NULL == sem)
451 return -EINVAL;
452
453 gpu_semaphore = calloc(1, sizeof(struct amdgpu_semaphore));
454 if (NULL == gpu_semaphore)
455 return -ENOMEM;
456
457 atomic_set(&gpu_semaphore->refcount, 1);
458 *sem = gpu_semaphore;
459
460 return 0;
461}
462
463int amdgpu_cs_signal_semaphore(amdgpu_context_handle ctx,
464 uint32_t ip_type,
465 uint32_t ip_instance,
466 uint32_t ring,
467 amdgpu_semaphore_handle sem)
468{
469 if (NULL == ctx)
470 return -EINVAL;
471 if (ip_type >= AMDGPU_HW_IP_NUM)
472 return -EINVAL;
473 if (ring >= AMDGPU_CS_MAX_RINGS)
474 return -EINVAL;
475 if (NULL == sem)
476 return -EINVAL;
477 /* sem has been signaled */
478 if (sem->signal_fence.context)
479 return -EINVAL;
480 pthread_mutex_lock(&ctx->sequence_mutex);
481 sem->signal_fence.context = ctx;
482 sem->signal_fence.ip_type = ip_type;
483 sem->signal_fence.ip_instance = ip_instance;
484 sem->signal_fence.ring = ring;
485 sem->signal_fence.fence = ctx->last_seq[ip_type][ip_instance][ring];
486 update_references(NULL, &sem->refcount);
487 pthread_mutex_unlock(&ctx->sequence_mutex);
488 return 0;
489}
490
491int amdgpu_cs_wait_semaphore(amdgpu_context_handle ctx,
492 uint32_t ip_type,
493 uint32_t ip_instance,
494 uint32_t ring,
495 amdgpu_semaphore_handle sem)
496{
497 if (NULL == ctx)
498 return -EINVAL;
499 if (ip_type >= AMDGPU_HW_IP_NUM)
500 return -EINVAL;
501 if (ring >= AMDGPU_CS_MAX_RINGS)
502 return -EINVAL;
503 if (NULL == sem)
504 return -EINVAL;
505 /* must signal first */
506 if (NULL == sem->signal_fence.context)
507 return -EINVAL;
508
509 pthread_mutex_lock(&ctx->sequence_mutex);
510 list_add(&sem->list, &ctx->sem_list[ip_type][ip_instance][ring]);
511 pthread_mutex_unlock(&ctx->sequence_mutex);
512 return 0;
513}
514
515static int amdgpu_cs_reset_sem(amdgpu_semaphore_handle sem)
516{
517 if (NULL == sem)
518 return -EINVAL;
519 if (NULL == sem->signal_fence.context)
520 return -EINVAL;
521
522 sem->signal_fence.context = NULL;;
523 sem->signal_fence.ip_type = 0;
524 sem->signal_fence.ip_instance = 0;
525 sem->signal_fence.ring = 0;
526 sem->signal_fence.fence = 0;
527
528 return 0;
529}
530
531static int amdgpu_cs_unreference_sem(amdgpu_semaphore_handle sem)
532{
533 if (NULL == sem)
534 return -EINVAL;
535
536 if (update_references(&sem->refcount, NULL))
537 free(sem);
538 return 0;
539}
540
541int amdgpu_cs_destroy_semaphore(amdgpu_semaphore_handle sem)
542{
543 return amdgpu_cs_unreference_sem(sem);
544}
diff --git a/amdgpu/amdgpu_device.c b/amdgpu/amdgpu_device.c
index e5a923e6..f4ede031 100644
--- a/amdgpu/amdgpu_device.c
+++ b/amdgpu/amdgpu_device.c
@@ -44,6 +44,7 @@
44#include "amdgpu_internal.h" 44#include "amdgpu_internal.h"
45#include "util_hash_table.h" 45#include "util_hash_table.h"
46#include "util_math.h" 46#include "util_math.h"
47#include "amdgpu_asic_id.h"
47 48
48#define PTR_TO_UINT(x) ((unsigned)((intptr_t)(x))) 49#define PTR_TO_UINT(x) ((unsigned)((intptr_t)(x)))
49#define UINT_TO_PTR(x) ((void *)((intptr_t)(x))) 50#define UINT_TO_PTR(x) ((void *)((intptr_t)(x)))
@@ -303,3 +304,17 @@ int amdgpu_device_deinitialize(amdgpu_device_handle dev)
303 amdgpu_device_reference(&dev, NULL); 304 amdgpu_device_reference(&dev, NULL);
304 return 0; 305 return 0;
305} 306}
307
308const char *amdgpu_get_marketing_name(amdgpu_device_handle dev)
309{
310 const struct amdgpu_asic_id_table_t *t = amdgpu_asic_id_table;
311
312 while (t->did) {
313 if ((t->did == dev->info.asic_id) &&
314 (t->rid == dev->info.pci_rev_id))
315 return t->marketing_name;
316 t++;
317 }
318
319 return NULL;
320}
diff --git a/amdgpu/amdgpu_gpu_info.c b/amdgpu/amdgpu_gpu_info.c
index 0cc17f1f..66c7e0e1 100644
--- a/amdgpu/amdgpu_gpu_info.c
+++ b/amdgpu/amdgpu_gpu_info.c
@@ -119,7 +119,7 @@ int amdgpu_query_firmware_version(amdgpu_device_handle dev, unsigned fw_type,
119 uint32_t *version, uint32_t *feature) 119 uint32_t *version, uint32_t *feature)
120{ 120{
121 struct drm_amdgpu_info request; 121 struct drm_amdgpu_info request;
122 struct drm_amdgpu_info_firmware firmware; 122 struct drm_amdgpu_info_firmware firmware = {};
123 int r; 123 int r;
124 124
125 memset(&request, 0, sizeof(request)); 125 memset(&request, 0, sizeof(request));
@@ -187,10 +187,12 @@ drm_private int amdgpu_query_gpu_info_init(amdgpu_device_handle dev)
187 if (r) 187 if (r)
188 return r; 188 return r;
189 189
190 r = amdgpu_read_mm_registers(dev, 0xa0d5, 1, instance, 0, 190 if (dev->info.family_id >= AMDGPU_FAMILY_CI) {
191 r = amdgpu_read_mm_registers(dev, 0xa0d5, 1, instance, 0,
191 &dev->info.pa_sc_raster_cfg1[i]); 192 &dev->info.pa_sc_raster_cfg1[i]);
192 if (r) 193 if (r)
193 return r; 194 return r;
195 }
194 } 196 }
195 197
196 r = amdgpu_read_mm_registers(dev, 0x2644, 32, 0xffffffff, 0, 198 r = amdgpu_read_mm_registers(dev, 0x2644, 32, 0xffffffff, 0,
@@ -198,10 +200,12 @@ drm_private int amdgpu_query_gpu_info_init(amdgpu_device_handle dev)
198 if (r) 200 if (r)
199 return r; 201 return r;
200 202
201 r = amdgpu_read_mm_registers(dev, 0x2664, 16, 0xffffffff, 0, 203 if (dev->info.family_id >= AMDGPU_FAMILY_CI) {
202 dev->info.gb_macro_tile_mode); 204 r = amdgpu_read_mm_registers(dev, 0x2664, 16, 0xffffffff, 0,
203 if (r) 205 dev->info.gb_macro_tile_mode);
204 return r; 206 if (r)
207 return r;
208 }
205 209
206 r = amdgpu_read_mm_registers(dev, 0x263e, 1, 0xffffffff, 0, 210 r = amdgpu_read_mm_registers(dev, 0x263e, 1, 0xffffffff, 0,
207 &dev->info.gb_addr_cfg); 211 &dev->info.gb_addr_cfg);
@@ -226,6 +230,8 @@ drm_private int amdgpu_query_gpu_info_init(amdgpu_device_handle dev)
226int amdgpu_query_gpu_info(amdgpu_device_handle dev, 230int amdgpu_query_gpu_info(amdgpu_device_handle dev,
227 struct amdgpu_gpu_info *info) 231 struct amdgpu_gpu_info *info)
228{ 232{
233 if ((dev == NULL) || (info == NULL))
234 return -EINVAL;
229 /* Get ASIC info*/ 235 /* Get ASIC info*/
230 *info = dev->info; 236 *info = dev->info;
231 237
diff --git a/amdgpu/amdgpu_internal.h b/amdgpu/amdgpu_internal.h
index 7dd5c1c7..4f039b68 100644
--- a/amdgpu/amdgpu_internal.h
+++ b/amdgpu/amdgpu_internal.h
@@ -44,6 +44,7 @@
44#define ROUND_DOWN(x, y) ((x) & ~__round_mask(x, y)) 44#define ROUND_DOWN(x, y) ((x) & ~__round_mask(x, y))
45 45
46#define AMDGPU_INVALID_VA_ADDRESS 0xffffffffffffffff 46#define AMDGPU_INVALID_VA_ADDRESS 0xffffffffffffffff
47#define AMDGPU_NULL_SUBMIT_SEQ 0
47 48
48struct amdgpu_bo_va_hole { 49struct amdgpu_bo_va_hole {
49 struct list_head list; 50 struct list_head list;
@@ -111,8 +112,23 @@ struct amdgpu_bo_list {
111 112
112struct amdgpu_context { 113struct amdgpu_context {
113 struct amdgpu_device *dev; 114 struct amdgpu_device *dev;
115 /** Mutex for accessing fences and to maintain command submissions
116 in good sequence. */
117 pthread_mutex_t sequence_mutex;
114 /* context id*/ 118 /* context id*/
115 uint32_t id; 119 uint32_t id;
120 uint64_t last_seq[AMDGPU_HW_IP_NUM][AMDGPU_HW_IP_INSTANCE_MAX_COUNT][AMDGPU_CS_MAX_RINGS];
121 struct list_head sem_list[AMDGPU_HW_IP_NUM][AMDGPU_HW_IP_INSTANCE_MAX_COUNT][AMDGPU_CS_MAX_RINGS];
122};
123
124/**
125 * Structure describing sw semaphore based on scheduler
126 *
127 */
128struct amdgpu_semaphore {
129 atomic_t refcount;
130 struct list_head list;
131 struct amdgpu_cs_fence signal_fence;
116}; 132};
117 133
118/** 134/**
diff --git a/amdgpu/libdrm_amdgpu.pc.in b/amdgpu/libdrm_amdgpu.pc.in
index 417865e5..f1c552a6 100644
--- a/amdgpu/libdrm_amdgpu.pc.in
+++ b/amdgpu/libdrm_amdgpu.pc.in
@@ -8,3 +8,4 @@ Description: Userspace interface to kernel DRM services for amdgpu
8Version: @PACKAGE_VERSION@ 8Version: @PACKAGE_VERSION@
9Libs: -L${libdir} -ldrm_amdgpu 9Libs: -L${libdir} -ldrm_amdgpu
10Cflags: -I${includedir} -I${includedir}/libdrm 10Cflags: -I${includedir} -I${includedir}/libdrm
11Requires.private: libdrm
diff --git a/autogen.sh b/autogen.sh
index c8960971..d82ab180 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -9,6 +9,12 @@ cd "$srcdir"
9autoreconf --force --verbose --install || exit 1 9autoreconf --force --verbose --install || exit 1
10cd "$ORIGDIR" || exit $? 10cd "$ORIGDIR" || exit $?
11 11
12git config --local --get format.subjectPrefix ||
13 git config --local format.subjectPrefix "PATCH libdrm" 2>/dev/null
14
15git config --local --get sendemail.to ||
16 git config --local sendemail.to "dri-devel@lists.freedesktop.org" 2>/dev/null
17
12if test -z "$NOCONFIGURE"; then 18if test -z "$NOCONFIGURE"; then
13 "$srcdir"/configure "$@" 19 "$srcdir"/configure "$@"
14fi 20fi
diff --git a/configure.ac b/configure.ac
index f729fd87..1da9d86b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -20,7 +20,7 @@
20 20
21AC_PREREQ([2.63]) 21AC_PREREQ([2.63])
22AC_INIT([libdrm], 22AC_INIT([libdrm],
23 [2.4.66], 23 [2.4.75],
24 [https://bugs.freedesktop.org/enter_bug.cgi?product=DRI], 24 [https://bugs.freedesktop.org/enter_bug.cgi?product=DRI],
25 [libdrm]) 25 [libdrm])
26 26
@@ -53,14 +53,15 @@ AC_USE_SYSTEM_EXTENSIONS
53AC_SYS_LARGEFILE 53AC_SYS_LARGEFILE
54AC_FUNC_ALLOCA 54AC_FUNC_ALLOCA
55 55
56AC_CHECK_HEADERS([sys/mkdev.h sys/sysctl.h]) 56AC_HEADER_MAJOR
57AC_CHECK_HEADERS([sys/sysctl.h sys/select.h])
57 58
58# Initialize libtool 59# Initialize libtool
59LT_PREREQ([2.2]) 60LT_PREREQ([2.2])
60LT_INIT([disable-static]) 61LT_INIT([disable-static])
61 62
62 63
63PKG_CHECK_MODULES(PTHREADSTUBS, pthread-stubs) 64
64AC_SUBST(PTHREADSTUBS_CFLAGS) 65AC_SUBST(PTHREADSTUBS_CFLAGS)
65AC_SUBST(PTHREADSTUBS_LIBS) 66AC_SUBST(PTHREADSTUBS_LIBS)
66 67
@@ -131,6 +132,16 @@ AC_ARG_ENABLE(rockchip-experimental-api,
131 [Enable support for rockchip's experimental API (default: disabled)]), 132 [Enable support for rockchip's experimental API (default: disabled)]),
132 [ROCKCHIP=$enableval], [ROCKCHIP=no]) 133 [ROCKCHIP=$enableval], [ROCKCHIP=no])
133 134
135AC_ARG_ENABLE(vc4,
136 AS_HELP_STRING([--disable-vc4],
137 [Enable support for vc4's API (default: auto, enabled on arm)]),
138 [VC4=$enableval], [VC4=auto])
139
140AC_ARG_ENABLE(etnaviv-experimental-api,
141 AS_HELP_STRING([--enable-etnaviv-experimental-api],
142 [Enable support for etnaviv's experimental API (default: disabled)]),
143 [ETNAVIV=$enableval], [ETNAVIV=no])
144
134AC_ARG_ENABLE(install-test-programs, 145AC_ARG_ENABLE(install-test-programs,
135 AS_HELP_STRING([--enable-install-test-programs], 146 AS_HELP_STRING([--enable-install-test-programs],
136 [Install test programs (default: no)]), 147 [Install test programs (default: no)]),
@@ -179,7 +190,8 @@ MAYBE_WARN="-Wall -Wextra \
179-Wstrict-aliasing=2 -Winit-self \ 190-Wstrict-aliasing=2 -Winit-self \
180-Wdeclaration-after-statement -Wold-style-definition \ 191-Wdeclaration-after-statement -Wold-style-definition \
181-Wno-unused-parameter \ 192-Wno-unused-parameter \
182-Wno-attributes -Wno-long-long -Winline -Wshadow" 193-Wno-attributes -Wno-long-long -Winline -Wshadow \
194-Wno-missing-field-initializers"
183 195
184# invalidate cached value if MAYBE_WARN has changed 196# invalidate cached value if MAYBE_WARN has changed
185if test "x$libdrm_cv_warn_maybe" != "x$MAYBE_WARN"; then 197if test "x$libdrm_cv_warn_maybe" != "x$MAYBE_WARN"; then
@@ -272,6 +284,9 @@ if test "x$drm_cv_atomic_primitives" = "xnone"; then
272 284
273 LIBDRM_ATOMICS_NOT_FOUND_MSG($TEGRA, tegra, NVIDIA Tegra, tegra-experimental-api) 285 LIBDRM_ATOMICS_NOT_FOUND_MSG($TEGRA, tegra, NVIDIA Tegra, tegra-experimental-api)
274 TEGRA=no 286 TEGRA=no
287
288 LIBDRM_ATOMICS_NOT_FOUND_MSG($ETNAVIV, etnaviv, Vivante, etnaviv-experimental-api)
289 ETNAVIV=no
275else 290else
276 if test "x$INTEL" = xauto; then 291 if test "x$INTEL" = xauto; then
277 case $host_cpu in 292 case $host_cpu in
@@ -294,6 +309,12 @@ else
294 *) FREEDRENO=no ;; 309 *) FREEDRENO=no ;;
295 esac 310 esac
296 fi 311 fi
312 if test "x$VC4" = xauto; then
313 case $host_cpu in
314 arm*|aarch64) VC4=yes ;;
315 *) VC4=no ;;
316 esac
317 fi
297fi 318fi
298 319
299if test "x$INTEL" != "xno"; then 320if test "x$INTEL" != "xno"; then
@@ -364,19 +385,23 @@ if test "x$RADEON" = xyes; then
364 AC_DEFINE(HAVE_RADEON, 1, [Have radeon support]) 385 AC_DEFINE(HAVE_RADEON, 1, [Have radeon support])
365fi 386fi
366 387
367# Detect cunit library 388if test "x$AMDGPU" != xno; then
368PKG_CHECK_MODULES([CUNIT], [cunit >= 2.1], [have_cunit=yes], [have_cunit=no]) 389 # Detect cunit library
369# If pkg-config does not find cunit, check it using AC_CHECK_LIB. We 390 PKG_CHECK_MODULES([CUNIT], [cunit >= 2.1], [have_cunit=yes], [have_cunit=no])
370# do this because Debian (Ubuntu) lacks pkg-config file for cunit. 391 # If pkg-config does not find cunit, check it using AC_CHECK_LIB. We
371# fixed in 2.1-2.dfsg-3: http://anonscm.debian.org/cgit/collab-maint/cunit.git/commit/?h=debian 392 # do this because Debian (Ubuntu) lacks pkg-config file for cunit.
372if test "x${have_cunit}" = "xno"; then 393 # fixed in 2.1-2.dfsg-3: http://anonscm.debian.org/cgit/collab-maint/cunit.git/commit/?h=debian
373 AC_CHECK_LIB([cunit], [CU_initialize_registry], [have_cunit=yes], [have_cunit=no]) 394 if test "x${have_cunit}" = "xno"; then
374 if test "x${have_cunit}" = "xyes"; then 395 AC_CHECK_LIB([cunit], [CU_initialize_registry], [have_cunit=yes], [have_cunit=no])
375 CUNIT_LIBS="-lcunit" 396 if test "x${have_cunit}" = "xyes"; then
376 CUNIT_CFLAGS="" 397 CUNIT_LIBS="-lcunit"
377 AC_SUBST([CUNIT_LIBS]) 398 CUNIT_CFLAGS=""
378 AC_SUBST([CUNIT_CFLAGS]) 399 AC_SUBST([CUNIT_LIBS])
400 AC_SUBST([CUNIT_CFLAGS])
401 fi
379 fi 402 fi
403else
404 have_cunit=no
380fi 405fi
381AM_CONDITIONAL(HAVE_CUNIT, [test "x$have_cunit" != "xno"]) 406AM_CONDITIONAL(HAVE_CUNIT, [test "x$have_cunit" != "xno"])
382 407
@@ -399,6 +424,15 @@ fi
399AM_CONDITIONAL(HAVE_ROCKCHIP, [test "x$ROCKCHIP" = xyes]) 424AM_CONDITIONAL(HAVE_ROCKCHIP, [test "x$ROCKCHIP" = xyes])
400if test "x$ROCKCHIP" = xyes; then 425if test "x$ROCKCHIP" = xyes; then
401 AC_DEFINE(HAVE_ROCKCHIP, 1, [Have ROCKCHIP support]) 426 AC_DEFINE(HAVE_ROCKCHIP, 1, [Have ROCKCHIP support])
427
428AM_CONDITIONAL(HAVE_VC4, [test "x$VC4" = xyes])
429if test "x$VC4" = xyes; then
430 AC_DEFINE(HAVE_VC4, 1, [Have VC4 support])
431fi
432
433AM_CONDITIONAL(HAVE_ETNAVIV, [test "x$ETNAVIV" = xyes])
434if test "x$ETNAVIV" = xyes; then
435 AC_DEFINE(HAVE_ETNAVIV, 1, [Have etnaviv support])
402fi 436fi
403 437
404AM_CONDITIONAL(HAVE_INSTALL_TESTS, [test "x$INSTALL_TESTS" = xyes]) 438AM_CONDITIONAL(HAVE_INSTALL_TESTS, [test "x$INSTALL_TESTS" = xyes])
@@ -410,7 +444,9 @@ AC_ARG_ENABLE([cairo-tests],
410 [AS_HELP_STRING([--enable-cairo-tests], 444 [AS_HELP_STRING([--enable-cairo-tests],
411 [Enable support for Cairo rendering in tests (default: auto)])], 445 [Enable support for Cairo rendering in tests (default: auto)])],
412 [CAIRO=$enableval], [CAIRO=auto]) 446 [CAIRO=$enableval], [CAIRO=auto])
413PKG_CHECK_MODULES(CAIRO, cairo, [HAVE_CAIRO=yes], [HAVE_CAIRO=no]) 447if test "x$CAIRO" != xno; then
448 PKG_CHECK_MODULES(CAIRO, cairo, [HAVE_CAIRO=yes], [HAVE_CAIRO=no])
449fi
414AC_MSG_CHECKING([whether to enable Cairo tests]) 450AC_MSG_CHECKING([whether to enable Cairo tests])
415if test "x$CAIRO" = xauto; then 451if test "x$CAIRO" = xauto; then
416 CAIRO="$HAVE_CAIRO" 452 CAIRO="$HAVE_CAIRO"
@@ -424,13 +460,6 @@ fi
424AC_MSG_RESULT([$CAIRO]) 460AC_MSG_RESULT([$CAIRO])
425AM_CONDITIONAL(HAVE_CAIRO, [test "x$CAIRO" = xyes]) 461AM_CONDITIONAL(HAVE_CAIRO, [test "x$CAIRO" = xyes])
426 462
427# For enumerating devices in test case
428PKG_CHECK_MODULES(LIBUDEV, libudev, [HAVE_LIBUDEV=yes], [HAVE_LIBUDEV=no])
429if test "x$HAVE_LIBUDEV" = xyes; then
430 AC_DEFINE(HAVE_LIBUDEV, 1, [Have libudev support])
431fi
432AM_CONDITIONAL(HAVE_LIBUDEV, [test "x$HAVE_LIBUDEV" = xyes])
433
434# xsltproc for docbook manpages 463# xsltproc for docbook manpages
435AC_ARG_ENABLE([manpages], 464AC_ARG_ENABLE([manpages],
436 AS_HELP_STRING([--enable-manpages], [enable manpages @<:@default=auto@:>@]), 465 AS_HELP_STRING([--enable-manpages], [enable manpages @<:@default=auto@:>@]),
@@ -455,7 +484,9 @@ AC_ARG_ENABLE(valgrind,
455 [AS_HELP_STRING([--enable-valgrind], 484 [AS_HELP_STRING([--enable-valgrind],
456 [Build libdrm with valgrind support (default: auto)])], 485 [Build libdrm with valgrind support (default: auto)])],
457 [VALGRIND=$enableval], [VALGRIND=auto]) 486 [VALGRIND=$enableval], [VALGRIND=auto])
458PKG_CHECK_MODULES(VALGRIND, [valgrind], [have_valgrind=yes], [have_valgrind=no]) 487if test "x$VALGRIND" != xno; then
488 PKG_CHECK_MODULES(VALGRIND, [valgrind], [have_valgrind=yes], [have_valgrind=no])
489fi
459AC_MSG_CHECKING([whether to enable Valgrind support]) 490AC_MSG_CHECKING([whether to enable Valgrind support])
460if test "x$VALGRIND" = xauto; then 491if test "x$VALGRIND" = xauto; then
461 VALGRIND="$have_valgrind" 492 VALGRIND="$have_valgrind"
@@ -508,6 +539,10 @@ AC_CONFIG_FILES([
508 tegra/libdrm_tegra.pc 539 tegra/libdrm_tegra.pc
509 rockchip/Makefile 540 rockchip/Makefile
510 rockchip/libdrm_rockchip.pc 541 rockchip/libdrm_rockchip.pc
542 vc4/Makefile
543 vc4/libdrm_vc4.pc
544 etnaviv/Makefile
545 etnaviv/libdrm_etnaviv.pc
511 tests/Makefile 546 tests/Makefile
512 tests/modeprint/Makefile 547 tests/modeprint/Makefile
513 tests/modetest/Makefile 548 tests/modetest/Makefile
@@ -521,6 +556,7 @@ AC_CONFIG_FILES([
521 tests/tegra/Makefile 556 tests/tegra/Makefile
522 tests/nouveau/Makefile 557 tests/nouveau/Makefile
523 tests/planetest/Makefile 558 tests/planetest/Makefile
559 tests/etnaviv/Makefile
524 tests/util/Makefile 560 tests/util/Makefile
525 man/Makefile 561 man/Makefile
526 libdrm.pc]) 562 libdrm.pc])
@@ -540,4 +576,6 @@ echo " EXYNOS API $EXYNOS"
540echo " Freedreno API $FREEDRENO (kgsl: $FREEDRENO_KGSL)" 576echo " Freedreno API $FREEDRENO (kgsl: $FREEDRENO_KGSL)"
541echo " Tegra API $TEGRA" 577echo " Tegra API $TEGRA"
542echo " Rockchip API $ROCKCHIP" 578echo " Rockchip API $ROCKCHIP"
579echo " VC4 API $VC4"
580echo " Etnaviv API $ETNAVIV"
543echo "" 581echo ""
diff --git a/etnaviv/Android.mk b/etnaviv/Android.mk
new file mode 100644
index 00000000..390f9a98
--- /dev/null
+++ b/etnaviv/Android.mk
@@ -0,0 +1,14 @@
1LOCAL_PATH := $(call my-dir)
2include $(CLEAR_VARS)
3
4# Import variables LIBDRM_ETNAVIV_FILES, LIBDRM_ETNAVIV_H_FILES
5include $(LOCAL_PATH)/Makefile.sources
6
7LOCAL_MODULE := libdrm_etnaviv
8
9LOCAL_SHARED_LIBRARIES := libdrm
10
11LOCAL_SRC_FILES := $(LIBDRM_ETNAVIV_FILES)
12
13include $(LIBDRM_COMMON_MK)
14include $(BUILD_SHARED_LIBRARY)
diff --git a/etnaviv/Makefile.am b/etnaviv/Makefile.am
new file mode 100644
index 00000000..be96ba86
--- /dev/null
+++ b/etnaviv/Makefile.am
@@ -0,0 +1,26 @@
1include Makefile.sources
2
3AM_CFLAGS = \
4 $(WARN_CFLAGS) \
5 -I$(top_srcdir) \
6 $(PTHREADSTUBS_CFLAGS) \
7 -I$(top_srcdir)/include/drm
8
9libdrm_etnaviv_ladir = $(libdir)
10libdrm_etnaviv_la_LTLIBRARIES = libdrm_etnaviv.la
11libdrm_etnaviv_la_LDFLAGS = -version-number 1:0:0 -no-undefined
12libdrm_etnaviv_la_LIBADD = \
13 ../libdrm.la \
14 @PTHREADSTUBS_LIBS@ \
15 @CLOCK_LIB@
16
17libdrm_etnaviv_la_SOURCES = $(LIBDRM_ETNAVIV_FILES)
18
19libdrm_etnavivincludedir = ${includedir}/libdrm
20libdrm_etnavivinclude_HEADERS = $(LIBDRM_ETNAVIV_H_FILES)
21
22pkgconfigdir = @pkgconfigdir@
23pkgconfig_DATA = libdrm_etnaviv.pc
24
25TESTS = etnaviv-symbol-check
26EXTRA_DIST = $(TESTS)
diff --git a/etnaviv/Makefile.sources b/etnaviv/Makefile.sources
new file mode 100644
index 00000000..52580567
--- /dev/null
+++ b/etnaviv/Makefile.sources
@@ -0,0 +1,12 @@
1LIBDRM_ETNAVIV_FILES := \
2 etnaviv_device.c \
3 etnaviv_gpu.c \
4 etnaviv_bo.c \
5 etnaviv_bo_cache.c \
6 etnaviv_pipe.c \
7 etnaviv_cmd_stream.c \
8 etnaviv_drm.h \
9 etnaviv_priv.h
10
11LIBDRM_ETNAVIV_H_FILES := \
12 etnaviv_drmif.h
diff --git a/etnaviv/etnaviv-symbol-check b/etnaviv/etnaviv-symbol-check
new file mode 100755
index 00000000..22afd168
--- /dev/null
+++ b/etnaviv/etnaviv-symbol-check
@@ -0,0 +1,48 @@
1#!/bin/bash
2
3# The following symbols (past the first five) are taken from the public headers.
4# A list of the latter should be available Makefile.sources/LIBDRM_ETNAVIV_H_FILES
5
6FUNCS=$(nm -D --format=bsd --defined-only ${1-.libs/libdrm_etnaviv.so} | awk '{print $3}'| while read func; do
7( grep -q "^$func$" || echo $func ) <<EOF
8__bss_start
9_edata
10_end
11_fini
12_init
13etna_device_new
14etna_device_new_dup
15etna_device_ref
16etna_device_del
17etna_device_fd
18etna_gpu_new
19etna_gpu_del
20etna_gpu_get_param
21etna_pipe_new
22etna_pipe_del
23etna_pipe_wait
24etna_pipe_wait_ns
25etna_bo_new
26etna_bo_from_handle
27etna_bo_from_name
28etna_bo_from_dmabuf
29etna_bo_ref
30etna_bo_del
31etna_bo_get_name
32etna_bo_handle
33etna_bo_dmabuf
34etna_bo_size
35etna_bo_map
36etna_bo_cpu_prep
37etna_bo_cpu_fini
38etna_cmd_stream_new
39etna_cmd_stream_del
40etna_cmd_stream_timestamp
41etna_cmd_stream_flush
42etna_cmd_stream_finish
43etna_cmd_stream_reloc
44EOF
45done)
46
47test ! -n "$FUNCS" || echo $FUNCS
48test ! -n "$FUNCS"
diff --git a/etnaviv/etnaviv_bo.c b/etnaviv/etnaviv_bo.c
new file mode 100644
index 00000000..4ad0434e
--- /dev/null
+++ b/etnaviv/etnaviv_bo.c
@@ -0,0 +1,347 @@
1/*
2 * Copyright (C) 2014 Etnaviv Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *
23 * Authors:
24 * Christian Gmeiner <christian.gmeiner@gmail.com>
25 */
26
27#ifdef HAVE_CONFIG_H
28# include <config.h>
29#endif
30
31#include "etnaviv_priv.h"
32#include "etnaviv_drmif.h"
33
34drm_private pthread_mutex_t table_lock = PTHREAD_MUTEX_INITIALIZER;
35drm_private void bo_del(struct etna_bo *bo);
36
37/* set buffer name, and add to table, call w/ table_lock held: */
38static void set_name(struct etna_bo *bo, uint32_t name)
39{
40 bo->name = name;
41 /* add ourself into the name table: */
42 drmHashInsert(bo->dev->name_table, name, bo);
43}
44
45/* Called under table_lock */
46drm_private void bo_del(struct etna_bo *bo)
47{
48 if (bo->map)
49 drm_munmap(bo->map, bo->size);
50
51 if (bo->name)
52 drmHashDelete(bo->dev->name_table, bo->name);
53
54 if (bo->handle) {
55 struct drm_gem_close req = {
56 .handle = bo->handle,
57 };
58
59 drmHashDelete(bo->dev->handle_table, bo->handle);
60 drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_CLOSE, &req);
61 }
62
63 free(bo);
64}
65
66/* lookup a buffer from it's handle, call w/ table_lock held: */
67static struct etna_bo *lookup_bo(void *tbl, uint32_t handle)
68{
69 struct etna_bo *bo = NULL;
70
71 if (!drmHashLookup(tbl, handle, (void **)&bo)) {
72 /* found, incr refcnt and return: */
73 bo = etna_bo_ref(bo);
74
75 /* don't break the bucket if this bo was found in one */
76 list_delinit(&bo->list);
77 }
78
79 return bo;
80}
81
82/* allocate a new buffer object, call w/ table_lock held */
83static struct etna_bo *bo_from_handle(struct etna_device *dev,
84 uint32_t size, uint32_t handle, uint32_t flags)
85{
86 struct etna_bo *bo = calloc(sizeof(*bo), 1);
87
88 if (!bo) {
89 struct drm_gem_close req = {
90 .handle = handle,
91 };
92
93 drmIoctl(dev->fd, DRM_IOCTL_GEM_CLOSE, &req);
94
95 return NULL;
96 }
97
98 bo->dev = etna_device_ref(dev);
99 bo->size = size;
100 bo->handle = handle;
101 bo->flags = flags;
102 atomic_set(&bo->refcnt, 1);
103 list_inithead(&bo->list);
104 /* add ourselves to the handle table: */
105 drmHashInsert(dev->handle_table, handle, bo);
106
107 return bo;
108}
109
110/* allocate a new (un-tiled) buffer object */
111struct etna_bo *etna_bo_new(struct etna_device *dev, uint32_t size,
112 uint32_t flags)
113{
114 struct etna_bo *bo;
115 int ret;
116 struct drm_etnaviv_gem_new req = {
117 .flags = flags,
118 };
119
120 bo = etna_bo_cache_alloc(&dev->bo_cache, &size, flags);
121 if (bo)
122 return bo;
123
124 req.size = size;
125 ret = drmCommandWriteRead(dev->fd, DRM_ETNAVIV_GEM_NEW,
126 &req, sizeof(req));
127 if (ret)
128 return NULL;
129
130 pthread_mutex_lock(&table_lock);
131 bo = bo_from_handle(dev, size, req.handle, flags);
132 bo->reuse = 1;
133 pthread_mutex_unlock(&table_lock);
134
135 return bo;
136}
137
138struct etna_bo *etna_bo_ref(struct etna_bo *bo)
139{
140 atomic_inc(&bo->refcnt);
141
142 return bo;
143}
144
145/* get buffer info */
146static int get_buffer_info(struct etna_bo *bo)
147{
148 int ret;
149 struct drm_etnaviv_gem_info req = {
150 .handle = bo->handle,
151 };
152
153 ret = drmCommandWriteRead(bo->dev->fd, DRM_ETNAVIV_GEM_INFO,
154 &req, sizeof(req));
155 if (ret) {
156 return ret;
157 }
158
159 /* really all we need for now is mmap offset */
160 bo->offset = req.offset;
161
162 return 0;
163}
164
165/* import a buffer object from DRI2 name */
166struct etna_bo *etna_bo_from_name(struct etna_device *dev, uint32_t name)
167{
168 struct etna_bo *bo;
169 struct drm_gem_open req = {
170 .name = name,
171 };
172
173 pthread_mutex_lock(&table_lock);
174
175 /* check name table first, to see if bo is already open: */
176 bo = lookup_bo(dev->name_table, req.handle);
177 if (bo)
178 goto out_unlock;
179
180 if (drmIoctl(dev->fd, DRM_IOCTL_GEM_OPEN, &req)) {
181 ERROR_MSG("gem-open failed: %s", strerror(errno));
182 goto out_unlock;
183 }
184
185 bo = lookup_bo(dev->handle_table, req.handle);
186 if (bo)
187 goto out_unlock;
188
189 bo = bo_from_handle(dev, req.size, req.handle, 0);
190 if (bo)
191 set_name(bo, name);
192
193out_unlock:
194 pthread_mutex_unlock(&table_lock);
195
196 return bo;
197}
198
199/* import a buffer from dmabuf fd, does not take ownership of the
200 * fd so caller should close() the fd when it is otherwise done
201 * with it (even if it is still using the 'struct etna_bo *')
202 */
203struct etna_bo *etna_bo_from_dmabuf(struct etna_device *dev, int fd)
204{
205 struct etna_bo *bo;
206 int ret, size;
207 uint32_t handle;
208
209 pthread_mutex_lock(&table_lock);
210
211 ret = drmPrimeFDToHandle(dev->fd, fd, &handle);
212 if (ret) {
213 return NULL;
214 }
215
216 bo = lookup_bo(dev->handle_table, handle);
217 if (bo)
218 goto out_unlock;
219
220 /* lseek() to get bo size */
221 size = lseek(fd, 0, SEEK_END);
222 lseek(fd, 0, SEEK_CUR);
223
224 bo = bo_from_handle(dev, size, handle, 0);
225
226out_unlock:
227 pthread_mutex_unlock(&table_lock);
228
229 return bo;
230}
231
232/* destroy a buffer object */
233void etna_bo_del(struct etna_bo *bo)
234{
235 struct etna_device *dev = bo->dev;
236
237 if (!bo)
238 return;
239
240 if (!atomic_dec_and_test(&bo->refcnt))
241 return;
242
243 pthread_mutex_lock(&table_lock);
244
245 if (bo->reuse && (etna_bo_cache_free(&dev->bo_cache, bo) == 0))
246 goto out;
247
248 bo_del(bo);
249 etna_device_del_locked(dev);
250out:
251 pthread_mutex_unlock(&table_lock);
252}
253
254/* get the global flink/DRI2 buffer name */
255int etna_bo_get_name(struct etna_bo *bo, uint32_t *name)
256{
257 if (!bo->name) {
258 struct drm_gem_flink req = {
259 .handle = bo->handle,
260 };
261 int ret;
262
263 ret = drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_FLINK, &req);
264 if (ret) {
265 return ret;
266 }
267
268 pthread_mutex_lock(&table_lock);
269 set_name(bo, req.name);
270 pthread_mutex_unlock(&table_lock);
271 bo->reuse = 0;
272 }
273
274 *name = bo->name;
275
276 return 0;
277}
278
279uint32_t etna_bo_handle(struct etna_bo *bo)
280{
281 return bo->handle;
282}
283
284/* caller owns the dmabuf fd that is returned and is responsible
285 * to close() it when done
286 */
287int etna_bo_dmabuf(struct etna_bo *bo)
288{
289 int ret, prime_fd;
290
291 ret = drmPrimeHandleToFD(bo->dev->fd, bo->handle, DRM_CLOEXEC,
292 &prime_fd);
293 if (ret) {
294 ERROR_MSG("failed to get dmabuf fd: %d", ret);
295 return ret;
296 }
297
298 bo->reuse = 0;
299
300 return prime_fd;
301}
302
303uint32_t etna_bo_size(struct etna_bo *bo)
304{
305 return bo->size;
306}
307
308void *etna_bo_map(struct etna_bo *bo)
309{
310 if (!bo->map) {
311 if (!bo->offset) {
312 get_buffer_info(bo);
313 }
314
315 bo->map = drm_mmap(0, bo->size, PROT_READ | PROT_WRITE,
316 MAP_SHARED, bo->dev->fd, bo->offset);
317 if (bo->map == MAP_FAILED) {
318 ERROR_MSG("mmap failed: %s", strerror(errno));
319 bo->map = NULL;
320 }
321 }
322
323 return bo->map;
324}
325
326int etna_bo_cpu_prep(struct etna_bo *bo, uint32_t op)
327{
328 struct drm_etnaviv_gem_cpu_prep req = {
329 .handle = bo->handle,
330 .op = op,
331 };
332
333 get_abs_timeout(&req.timeout, 5000000000);
334
335 return drmCommandWrite(bo->dev->fd, DRM_ETNAVIV_GEM_CPU_PREP,
336 &req, sizeof(req));
337}
338
339void etna_bo_cpu_fini(struct etna_bo *bo)
340{
341 struct drm_etnaviv_gem_cpu_fini req = {
342 .handle = bo->handle,
343 };
344
345 drmCommandWrite(bo->dev->fd, DRM_ETNAVIV_GEM_CPU_FINI,
346 &req, sizeof(req));
347}
diff --git a/etnaviv/etnaviv_bo_cache.c b/etnaviv/etnaviv_bo_cache.c
new file mode 100644
index 00000000..8924651f
--- /dev/null
+++ b/etnaviv/etnaviv_bo_cache.c
@@ -0,0 +1,196 @@
1/*
2 * Copyright (C) 2016 Etnaviv Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *
23 * Authors:
24 * Christian Gmeiner <christian.gmeiner@gmail.com>
25 */
26
27#ifdef HAVE_CONFIG_H
28# include <config.h>
29#endif
30
31#include "etnaviv_priv.h"
32#include "etnaviv_drmif.h"
33
34drm_private void bo_del(struct etna_bo *bo);
35drm_private extern pthread_mutex_t table_lock;
36
37static void add_bucket(struct etna_bo_cache *cache, int size)
38{
39 unsigned i = cache->num_buckets;
40
41 assert(i < ARRAY_SIZE(cache->cache_bucket));
42
43 list_inithead(&cache->cache_bucket[i].list);
44 cache->cache_bucket[i].size = size;
45 cache->num_buckets++;
46}
47
48drm_private void etna_bo_cache_init(struct etna_bo_cache *cache)
49{
50 unsigned long size, cache_max_size = 64 * 1024 * 1024;
51
52 /* OK, so power of two buckets was too wasteful of memory.
53 * Give 3 other sizes between each power of two, to hopefully
54 * cover things accurately enough. (The alternative is
55 * probably to just go for exact matching of sizes, and assume
56 * that for things like composited window resize the tiled
57 * width/height alignment and rounding of sizes to pages will
58 * get us useful cache hit rates anyway)
59 */
60 add_bucket(cache, 4096);
61 add_bucket(cache, 4096 * 2);
62 add_bucket(cache, 4096 * 3);
63
64 /* Initialize the linked lists for BO reuse cache. */
65 for (size = 4 * 4096; size <= cache_max_size; size *= 2) {
66 add_bucket(cache, size);
67 add_bucket(cache, size + size * 1 / 4);
68 add_bucket(cache, size + size * 2 / 4);
69 add_bucket(cache, size + size * 3 / 4);
70 }
71}
72
73/* Frees older cached buffers. Called under table_lock */
74drm_private void etna_bo_cache_cleanup(struct etna_bo_cache *cache, time_t time)
75{
76 unsigned i;
77
78 if (cache->time == time)
79 return;
80
81 for (i = 0; i < cache->num_buckets; i++) {
82 struct etna_bo_bucket *bucket = &cache->cache_bucket[i];
83 struct etna_bo *bo;
84
85 while (!LIST_IS_EMPTY(&bucket->list)) {
86 bo = LIST_ENTRY(struct etna_bo, bucket->list.next, list);
87
88 /* keep things in cache for at least 1 second: */
89 if (time && ((time - bo->free_time) <= 1))
90 break;
91
92 list_del(&bo->list);
93 bo_del(bo);
94 }
95 }
96
97 cache->time = time;
98}
99
100static struct etna_bo_bucket *get_bucket(struct etna_bo_cache *cache, uint32_t size)
101{
102 unsigned i;
103
104 /* hmm, this is what intel does, but I suppose we could calculate our
105 * way to the correct bucket size rather than looping..
106 */
107 for (i = 0; i < cache->num_buckets; i++) {
108 struct etna_bo_bucket *bucket = &cache->cache_bucket[i];
109 if (bucket->size >= size) {
110 return bucket;
111 }
112 }
113
114 return NULL;
115}
116
117static int is_idle(struct etna_bo *bo)
118{
119 return etna_bo_cpu_prep(bo,
120 DRM_ETNA_PREP_READ |
121 DRM_ETNA_PREP_WRITE |
122 DRM_ETNA_PREP_NOSYNC) == 0;
123}
124
125static struct etna_bo *find_in_bucket(struct etna_bo_bucket *bucket, uint32_t flags)
126{
127 struct etna_bo *bo = NULL;
128
129 pthread_mutex_lock(&table_lock);
130 while (!LIST_IS_EMPTY(&bucket->list)) {
131 bo = LIST_ENTRY(struct etna_bo, bucket->list.next, list);
132
133 if (bo->flags == flags && is_idle(bo)) {
134 list_del(&bo->list);
135 break;
136 }
137
138 bo = NULL;
139 break;
140 }
141 pthread_mutex_unlock(&table_lock);
142
143 return bo;
144}
145
146/* allocate a new (un-tiled) buffer object
147 *
148 * NOTE: size is potentially rounded up to bucket size
149 */
150drm_private struct etna_bo *etna_bo_cache_alloc(struct etna_bo_cache *cache, uint32_t *size,
151 uint32_t flags)
152{
153 struct etna_bo *bo;
154 struct etna_bo_bucket *bucket;
155
156 *size = ALIGN(*size, 4096);
157 bucket = get_bucket(cache, *size);
158
159 /* see if we can be green and recycle: */
160 if (bucket) {
161 *size = bucket->size;
162 bo = find_in_bucket(bucket, flags);
163 if (bo) {
164 atomic_set(&bo->refcnt, 1);
165 etna_device_ref(bo->dev);
166 return bo;
167 }
168 }
169
170 return NULL;
171}
172
173drm_private int etna_bo_cache_free(struct etna_bo_cache *cache, struct etna_bo *bo)
174{
175 struct etna_bo_bucket *bucket = get_bucket(cache, bo->size);
176
177 /* see if we can be green and recycle: */
178 if (bucket) {
179 struct timespec time;
180
181 clock_gettime(CLOCK_MONOTONIC, &time);
182
183 bo->free_time = time.tv_sec;
184 list_addtail(&bo->list, &bucket->list);
185 etna_bo_cache_cleanup(cache, time.tv_sec);
186
187 /* bo's in the bucket cache don't have a ref and
188 * don't hold a ref to the dev:
189 */
190 etna_device_del_locked(bo->dev);
191
192 return 0;
193 }
194
195 return -1;
196}
diff --git a/etnaviv/etnaviv_cmd_stream.c b/etnaviv/etnaviv_cmd_stream.c
new file mode 100644
index 00000000..9ce3f363
--- /dev/null
+++ b/etnaviv/etnaviv_cmd_stream.c
@@ -0,0 +1,243 @@
1/*
2 * Copyright (C) 2014-2015 Etnaviv Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *
23 * Authors:
24 * Christian Gmeiner <christian.gmeiner@gmail.com>
25 */
26
27#ifdef HAVE_CONFIG_H
28# include <config.h>
29#endif
30
31#include <assert.h>
32
33#include "etnaviv_drmif.h"
34#include "etnaviv_priv.h"
35
36static pthread_mutex_t idx_lock = PTHREAD_MUTEX_INITIALIZER;
37
38static void *grow(void *ptr, uint32_t nr, uint32_t *max, uint32_t sz)
39{
40 if ((nr + 1) > *max) {
41 if ((*max * 2) < (nr + 1))
42 *max = nr + 5;
43 else
44 *max = *max * 2;
45 ptr = realloc(ptr, *max * sz);
46 }
47
48 return ptr;
49}
50
51#define APPEND(x, name) ({ \
52 (x)->name = grow((x)->name, (x)->nr_ ## name, &(x)->max_ ## name, sizeof((x)->name[0])); \
53 (x)->nr_ ## name ++; \
54})
55
56static inline struct etna_cmd_stream_priv *
57etna_cmd_stream_priv(struct etna_cmd_stream *stream)
58{
59 return (struct etna_cmd_stream_priv *)stream;
60}
61
62struct etna_cmd_stream *etna_cmd_stream_new(struct etna_pipe *pipe, uint32_t size,
63 void (*reset_notify)(struct etna_cmd_stream *stream, void *priv),
64 void *priv)
65{
66 struct etna_cmd_stream_priv *stream = NULL;
67
68 if (size == 0) {
69 ERROR_MSG("invalid size of 0");
70 goto fail;
71 }
72
73 stream = calloc(1, sizeof(*stream));
74 if (!stream) {
75 ERROR_MSG("allocation failed");
76 goto fail;
77 }
78
79 /* allocate even number of 32-bit words */
80 size = ALIGN(size, 2);
81
82 stream->base.buffer = malloc(size * sizeof(uint32_t));
83 if (!stream->base.buffer) {
84 ERROR_MSG("allocation failed");
85 goto fail;
86 }
87
88 stream->base.size = size;
89 stream->pipe = pipe;
90 stream->reset_notify = reset_notify;
91 stream->reset_notify_priv = priv;
92
93 return &stream->base;
94
95fail:
96 if (stream)
97 etna_cmd_stream_del(&stream->base);
98
99 return NULL;
100}
101
102void etna_cmd_stream_del(struct etna_cmd_stream *stream)
103{
104 struct etna_cmd_stream_priv *priv = etna_cmd_stream_priv(stream);
105
106 free(stream->buffer);
107 free(priv->submit.relocs);
108 free(priv);
109}
110
111static void reset_buffer(struct etna_cmd_stream *stream)
112{
113 struct etna_cmd_stream_priv *priv = etna_cmd_stream_priv(stream);
114
115 stream->offset = 0;
116 priv->submit.nr_bos = 0;
117 priv->submit.nr_relocs = 0;
118 priv->nr_bos = 0;
119
120 if (priv->reset_notify)
121 priv->reset_notify(stream, priv->reset_notify_priv);
122}
123
124uint32_t etna_cmd_stream_timestamp(struct etna_cmd_stream *stream)
125{
126 return etna_cmd_stream_priv(stream)->last_timestamp;
127}
128
129static uint32_t append_bo(struct etna_cmd_stream *stream, struct etna_bo *bo)
130{
131 struct etna_cmd_stream_priv *priv = etna_cmd_stream_priv(stream);
132 uint32_t idx;
133
134 idx = APPEND(&priv->submit, bos);
135 idx = APPEND(priv, bos);
136
137 priv->submit.bos[idx].flags = 0;
138 priv->submit.bos[idx].handle = bo->handle;
139
140 priv->bos[idx] = etna_bo_ref(bo);
141
142 return idx;
143}
144
145/* add (if needed) bo, return idx: */
146static uint32_t bo2idx(struct etna_cmd_stream *stream, struct etna_bo *bo,
147 uint32_t flags)
148{
149 struct etna_cmd_stream_priv *priv = etna_cmd_stream_priv(stream);
150 uint32_t idx;
151
152 pthread_mutex_lock(&idx_lock);
153
154 if (!bo->current_stream) {
155 idx = append_bo(stream, bo);
156 bo->current_stream = stream;
157 bo->idx = idx;
158 } else if (bo->current_stream == stream) {
159 idx = bo->idx;
160 } else {
161 /* slow-path: */
162 for (idx = 0; idx < priv->nr_bos; idx++)
163 if (priv->bos[idx] == bo)
164 break;
165 if (idx == priv->nr_bos) {
166 /* not found */
167 idx = append_bo(stream, bo);
168 }
169 }
170 pthread_mutex_unlock(&idx_lock);
171
172 if (flags & ETNA_RELOC_READ)
173 priv->submit.bos[idx].flags |= ETNA_SUBMIT_BO_READ;
174 if (flags & ETNA_RELOC_WRITE)
175 priv->submit.bos[idx].flags |= ETNA_SUBMIT_BO_WRITE;
176
177 return idx;
178}
179
180static void flush(struct etna_cmd_stream *stream)
181{
182 struct etna_cmd_stream_priv *priv = etna_cmd_stream_priv(stream);
183 int ret, id = priv->pipe->id;
184 struct etna_gpu *gpu = priv->pipe->gpu;
185
186 struct drm_etnaviv_gem_submit req = {
187 .pipe = gpu->core,
188 .exec_state = id,
189 .bos = VOID2U64(priv->submit.bos),
190 .nr_bos = priv->submit.nr_bos,
191 .relocs = VOID2U64(priv->submit.relocs),
192 .nr_relocs = priv->submit.nr_relocs,
193 .stream = VOID2U64(stream->buffer),
194 .stream_size = stream->offset * 4, /* in bytes */
195 };
196
197 ret = drmCommandWriteRead(gpu->dev->fd, DRM_ETNAVIV_GEM_SUBMIT,
198 &req, sizeof(req));
199
200 if (ret)
201 ERROR_MSG("submit failed: %d (%s)", ret, strerror(errno));
202 else
203 priv->last_timestamp = req.fence;
204
205 for (uint32_t i = 0; i < priv->nr_bos; i++) {
206 struct etna_bo *bo = priv->bos[i];
207
208 bo->current_stream = NULL;
209 etna_bo_del(bo);
210 }
211}
212
213void etna_cmd_stream_flush(struct etna_cmd_stream *stream)
214{
215 flush(stream);
216 reset_buffer(stream);
217}
218
219void etna_cmd_stream_finish(struct etna_cmd_stream *stream)
220{
221 struct etna_cmd_stream_priv *priv = etna_cmd_stream_priv(stream);
222
223 flush(stream);
224 etna_pipe_wait(priv->pipe, priv->last_timestamp, 5000);
225 reset_buffer(stream);
226}
227
228void etna_cmd_stream_reloc(struct etna_cmd_stream *stream, const struct etna_reloc *r)
229{
230 struct etna_cmd_stream_priv *priv = etna_cmd_stream_priv(stream);
231 struct drm_etnaviv_gem_submit_reloc *reloc;
232 uint32_t idx = APPEND(&priv->submit, relocs);
233 uint32_t addr = 0;
234
235 reloc = &priv->submit.relocs[idx];
236
237 reloc->reloc_idx = bo2idx(stream, r->bo, r->flags);
238 reloc->reloc_offset = r->offset;
239 reloc->submit_offset = stream->offset * 4; /* in bytes */
240 reloc->flags = 0;
241
242 etna_cmd_stream_emit(stream, addr);
243}
diff --git a/etnaviv/etnaviv_device.c b/etnaviv/etnaviv_device.c
new file mode 100644
index 00000000..3ce92030
--- /dev/null
+++ b/etnaviv/etnaviv_device.c
@@ -0,0 +1,119 @@
1/*
2 * Copyright (C) 2014 Etnaviv Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *
23 * Authors:
24 * Christian Gmeiner <christian.gmeiner@gmail.com>
25 */
26
27#ifdef HAVE_CONFIG_H
28#include "config.h"
29#endif
30
31#include <stdlib.h>
32#include <linux/stddef.h>
33#include <linux/types.h>
34#include <errno.h>
35#include <sys/mman.h>
36#include <fcntl.h>
37#include <unistd.h>
38#include <pthread.h>
39
40#include <xf86drm.h>
41#include <xf86atomic.h>
42
43#include "etnaviv_priv.h"
44#include "etnaviv_drmif.h"
45
46static pthread_mutex_t table_lock = PTHREAD_MUTEX_INITIALIZER;
47
48struct etna_device *etna_device_new(int fd)
49{
50 struct etna_device *dev = calloc(sizeof(*dev), 1);
51
52 if (!dev)
53 return NULL;
54
55 atomic_set(&dev->refcnt, 1);
56 dev->fd = fd;
57 dev->handle_table = drmHashCreate();
58 dev->name_table = drmHashCreate();
59 etna_bo_cache_init(&dev->bo_cache);
60
61 return dev;
62}
63
64/* like etna_device_new() but creates it's own private dup() of the fd
65 * which is close()d when the device is finalized. */
66struct etna_device *etna_device_new_dup(int fd)
67{
68 int dup_fd = dup(fd);
69 struct etna_device *dev = etna_device_new(dup_fd);
70
71 if (dev)
72 dev->closefd = 1;
73 else
74 close(dup_fd);
75
76 return dev;
77}
78
79struct etna_device *etna_device_ref(struct etna_device *dev)
80{
81 atomic_inc(&dev->refcnt);
82
83 return dev;
84}
85
86static void etna_device_del_impl(struct etna_device *dev)
87{
88 etna_bo_cache_cleanup(&dev->bo_cache, 0);
89 drmHashDestroy(dev->handle_table);
90 drmHashDestroy(dev->name_table);
91
92 if (dev->closefd)
93 close(dev->fd);
94
95 free(dev);
96}
97
98drm_private void etna_device_del_locked(struct etna_device *dev)
99{
100 if (!atomic_dec_and_test(&dev->refcnt))
101 return;
102
103 etna_device_del_impl(dev);
104}
105
106void etna_device_del(struct etna_device *dev)
107{
108 if (!atomic_dec_and_test(&dev->refcnt))
109 return;
110
111 pthread_mutex_lock(&table_lock);
112 etna_device_del_impl(dev);
113 pthread_mutex_unlock(&table_lock);
114}
115
116int etna_device_fd(struct etna_device *dev)
117{
118 return dev->fd;
119}
diff --git a/etnaviv/etnaviv_drm.h b/etnaviv/etnaviv_drm.h
new file mode 100644
index 00000000..2584c1cc
--- /dev/null
+++ b/etnaviv/etnaviv_drm.h
@@ -0,0 +1,233 @@
1/*
2 * Copyright (C) 2015 Etnaviv Project
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 as published by
6 * the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#ifndef __ETNAVIV_DRM_H__
18#define __ETNAVIV_DRM_H__
19
20#include "drm.h"
21
22#if defined(__cplusplus)
23extern "C" {
24#endif
25
26/* Please note that modifications to all structs defined here are
27 * subject to backwards-compatibility constraints:
28 * 1) Do not use pointers, use __u64 instead for 32 bit / 64 bit
29 * user/kernel compatibility
30 * 2) Keep fields aligned to their size
31 * 3) Because of how drm_ioctl() works, we can add new fields at
32 * the end of an ioctl if some care is taken: drm_ioctl() will
33 * zero out the new fields at the tail of the ioctl, so a zero
34 * value should have a backwards compatible meaning. And for
35 * output params, userspace won't see the newly added output
36 * fields.. so that has to be somehow ok.
37 */
38
39/* timeouts are specified in clock-monotonic absolute times (to simplify
40 * restarting interrupted ioctls). The following struct is logically the
41 * same as 'struct timespec' but 32/64b ABI safe.
42 */
43struct drm_etnaviv_timespec {
44 __s64 tv_sec; /* seconds */
45 __s64 tv_nsec; /* nanoseconds */
46};
47
48#define ETNAVIV_PARAM_GPU_MODEL 0x01
49#define ETNAVIV_PARAM_GPU_REVISION 0x02
50#define ETNAVIV_PARAM_GPU_FEATURES_0 0x03
51#define ETNAVIV_PARAM_GPU_FEATURES_1 0x04
52#define ETNAVIV_PARAM_GPU_FEATURES_2 0x05
53#define ETNAVIV_PARAM_GPU_FEATURES_3 0x06
54#define ETNAVIV_PARAM_GPU_FEATURES_4 0x07
55#define ETNAVIV_PARAM_GPU_FEATURES_5 0x08
56#define ETNAVIV_PARAM_GPU_FEATURES_6 0x09
57
58#define ETNAVIV_PARAM_GPU_STREAM_COUNT 0x10
59#define ETNAVIV_PARAM_GPU_REGISTER_MAX 0x11
60#define ETNAVIV_PARAM_GPU_THREAD_COUNT 0x12
61#define ETNAVIV_PARAM_GPU_VERTEX_CACHE_SIZE 0x13
62#define ETNAVIV_PARAM_GPU_SHADER_CORE_COUNT 0x14
63#define ETNAVIV_PARAM_GPU_PIXEL_PIPES 0x15
64#define ETNAVIV_PARAM_GPU_VERTEX_OUTPUT_BUFFER_SIZE 0x16
65#define ETNAVIV_PARAM_GPU_BUFFER_SIZE 0x17
66#define ETNAVIV_PARAM_GPU_INSTRUCTION_COUNT 0x18
67#define ETNAVIV_PARAM_GPU_NUM_CONSTANTS 0x19
68#define ETNAVIV_PARAM_GPU_NUM_VARYINGS 0x1a
69
70#define ETNA_MAX_PIPES 4
71
72struct drm_etnaviv_param {
73 __u32 pipe; /* in */
74 __u32 param; /* in, ETNAVIV_PARAM_x */
75 __u64 value; /* out (get_param) or in (set_param) */
76};
77
78/*
79 * GEM buffers:
80 */
81
82#define ETNA_BO_CACHE_MASK 0x000f0000
83/* cache modes */
84#define ETNA_BO_CACHED 0x00010000
85#define ETNA_BO_WC 0x00020000
86#define ETNA_BO_UNCACHED 0x00040000
87/* map flags */
88#define ETNA_BO_FORCE_MMU 0x00100000
89
90struct drm_etnaviv_gem_new {
91 __u64 size; /* in */
92 __u32 flags; /* in, mask of ETNA_BO_x */
93 __u32 handle; /* out */
94};
95
96struct drm_etnaviv_gem_info {
97 __u32 handle; /* in */
98 __u32 pad;
99 __u64 offset; /* out, offset to pass to mmap() */
100};
101
102#define ETNA_PREP_READ 0x01
103#define ETNA_PREP_WRITE 0x02
104#define ETNA_PREP_NOSYNC 0x04
105
106struct drm_etnaviv_gem_cpu_prep {
107 __u32 handle; /* in */
108 __u32 op; /* in, mask of ETNA_PREP_x */
109 struct drm_etnaviv_timespec timeout; /* in */
110};
111
112struct drm_etnaviv_gem_cpu_fini {
113 __u32 handle; /* in */
114 __u32 flags; /* in, placeholder for now, no defined values */
115};
116
117/*
118 * Cmdstream Submission:
119 */
120
121/* The value written into the cmdstream is logically:
122 * relocbuf->gpuaddr + reloc_offset
123 *
124 * NOTE that reloc's must be sorted by order of increasing submit_offset,
125 * otherwise EINVAL.
126 */
127struct drm_etnaviv_gem_submit_reloc {
128 __u32 submit_offset; /* in, offset from submit_bo */
129 __u32 reloc_idx; /* in, index of reloc_bo buffer */
130 __u64 reloc_offset; /* in, offset from start of reloc_bo */
131 __u32 flags; /* in, placeholder for now, no defined values */
132};
133
134/* Each buffer referenced elsewhere in the cmdstream submit (ie. the
135 * cmdstream buffer(s) themselves or reloc entries) has one (and only
136 * one) entry in the submit->bos[] table.
137 *
138 * As a optimization, the current buffer (gpu virtual address) can be
139 * passed back through the 'presumed' field. If on a subsequent reloc,
140 * userspace passes back a 'presumed' address that is still valid,
141 * then patching the cmdstream for this entry is skipped. This can
142 * avoid kernel needing to map/access the cmdstream bo in the common
143 * case.
144 */
145#define ETNA_SUBMIT_BO_READ 0x0001
146#define ETNA_SUBMIT_BO_WRITE 0x0002
147struct drm_etnaviv_gem_submit_bo {
148 __u32 flags; /* in, mask of ETNA_SUBMIT_BO_x */
149 __u32 handle; /* in, GEM handle */
150 __u64 presumed; /* in/out, presumed buffer address */
151};
152
153/* Each cmdstream submit consists of a table of buffers involved, and
154 * one or more cmdstream buffers. This allows for conditional execution
155 * (context-restore), and IB buffers needed for per tile/bin draw cmds.
156 */
157#define ETNA_PIPE_3D 0x00
158#define ETNA_PIPE_2D 0x01
159#define ETNA_PIPE_VG 0x02
160struct drm_etnaviv_gem_submit {
161 __u32 fence; /* out */
162 __u32 pipe; /* in */
163 __u32 exec_state; /* in, initial execution state (ETNA_PIPE_x) */
164 __u32 nr_bos; /* in, number of submit_bo's */
165 __u32 nr_relocs; /* in, number of submit_reloc's */
166 __u32 stream_size; /* in, cmdstream size */
167 __u64 bos; /* in, ptr to array of submit_bo's */
168 __u64 relocs; /* in, ptr to array of submit_reloc's */
169 __u64 stream; /* in, ptr to cmdstream */
170};
171
172/* The normal way to synchronize with the GPU is just to CPU_PREP on
173 * a buffer if you need to access it from the CPU (other cmdstream
174 * submission from same or other contexts, PAGE_FLIP ioctl, etc, all
175 * handle the required synchronization under the hood). This ioctl
176 * mainly just exists as a way to implement the gallium pipe_fence
177 * APIs without requiring a dummy bo to synchronize on.
178 */
179#define ETNA_WAIT_NONBLOCK 0x01
180struct drm_etnaviv_wait_fence {
181 __u32 pipe; /* in */
182 __u32 fence; /* in */
183 __u32 flags; /* in, mask of ETNA_WAIT_x */
184 __u32 pad;
185 struct drm_etnaviv_timespec timeout; /* in */
186};
187
188#define ETNA_USERPTR_READ 0x01
189#define ETNA_USERPTR_WRITE 0x02
190struct drm_etnaviv_gem_userptr {
191 __u64 user_ptr; /* in, page aligned user pointer */
192 __u64 user_size; /* in, page aligned user size */
193 __u32 flags; /* in, flags */
194 __u32 handle; /* out, non-zero handle */
195};
196
197struct drm_etnaviv_gem_wait {
198 __u32 pipe; /* in */
199 __u32 handle; /* in, bo to be waited for */
200 __u32 flags; /* in, mask of ETNA_WAIT_x */
201 __u32 pad;
202 struct drm_etnaviv_timespec timeout; /* in */
203};
204
205#define DRM_ETNAVIV_GET_PARAM 0x00
206/* placeholder:
207#define DRM_ETNAVIV_SET_PARAM 0x01
208 */
209#define DRM_ETNAVIV_GEM_NEW 0x02
210#define DRM_ETNAVIV_GEM_INFO 0x03
211#define DRM_ETNAVIV_GEM_CPU_PREP 0x04
212#define DRM_ETNAVIV_GEM_CPU_FINI 0x05
213#define DRM_ETNAVIV_GEM_SUBMIT 0x06
214#define DRM_ETNAVIV_WAIT_FENCE 0x07
215#define DRM_ETNAVIV_GEM_USERPTR 0x08
216#define DRM_ETNAVIV_GEM_WAIT 0x09
217#define DRM_ETNAVIV_NUM_IOCTLS 0x0a
218
219#define DRM_IOCTL_ETNAVIV_GET_PARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_GET_PARAM, struct drm_etnaviv_param)
220#define DRM_IOCTL_ETNAVIV_GEM_NEW DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_GEM_NEW, struct drm_etnaviv_gem_new)
221#define DRM_IOCTL_ETNAVIV_GEM_INFO DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_GEM_INFO, struct drm_etnaviv_gem_info)
222#define DRM_IOCTL_ETNAVIV_GEM_CPU_PREP DRM_IOW(DRM_COMMAND_BASE + DRM_ETNAVIV_GEM_CPU_PREP, struct drm_etnaviv_gem_cpu_prep)
223#define DRM_IOCTL_ETNAVIV_GEM_CPU_FINI DRM_IOW(DRM_COMMAND_BASE + DRM_ETNAVIV_GEM_CPU_FINI, struct drm_etnaviv_gem_cpu_fini)
224#define DRM_IOCTL_ETNAVIV_GEM_SUBMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_GEM_SUBMIT, struct drm_etnaviv_gem_submit)
225#define DRM_IOCTL_ETNAVIV_WAIT_FENCE DRM_IOW(DRM_COMMAND_BASE + DRM_ETNAVIV_WAIT_FENCE, struct drm_etnaviv_wait_fence)
226#define DRM_IOCTL_ETNAVIV_GEM_USERPTR DRM_IOWR(DRM_COMMAND_BASE + DRM_ETNAVIV_GEM_USERPTR, struct drm_etnaviv_gem_userptr)
227#define DRM_IOCTL_ETNAVIV_GEM_WAIT DRM_IOW(DRM_COMMAND_BASE + DRM_ETNAVIV_GEM_WAIT, struct drm_etnaviv_gem_wait)
228
229#if defined(__cplusplus)
230}
231#endif
232
233#endif /* __ETNAVIV_DRM_H__ */
diff --git a/etnaviv/etnaviv_drmif.h b/etnaviv/etnaviv_drmif.h
new file mode 100644
index 00000000..8119baad
--- /dev/null
+++ b/etnaviv/etnaviv_drmif.h
@@ -0,0 +1,191 @@
1/*
2 * Copyright (C) 2014-2015 Etnaviv Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *
23 * Authors:
24 * Christian Gmeiner <christian.gmeiner@gmail.com>
25 */
26
27#ifndef ETNAVIV_DRMIF_H_
28#define ETNAVIV_DRMIF_H_
29
30#include <xf86drm.h>
31#include <stdint.h>
32
33struct etna_bo;
34struct etna_pipe;
35struct etna_gpu;
36struct etna_device;
37struct etna_cmd_stream;
38
39enum etna_pipe_id {
40 ETNA_PIPE_3D = 0,
41 ETNA_PIPE_2D = 1,
42 ETNA_PIPE_VG = 2,
43 ETNA_PIPE_MAX
44};
45
46enum etna_param_id {
47 ETNA_GPU_MODEL = 0x1,
48 ETNA_GPU_REVISION = 0x2,
49 ETNA_GPU_FEATURES_0 = 0x3,
50 ETNA_GPU_FEATURES_1 = 0x4,
51 ETNA_GPU_FEATURES_2 = 0x5,
52 ETNA_GPU_FEATURES_3 = 0x6,
53 ETNA_GPU_FEATURES_4 = 0x7,
54 ETNA_GPU_FEATURES_5 = 0x8,
55 ETNA_GPU_FEATURES_6 = 0x9,
56
57 ETNA_GPU_STREAM_COUNT = 0x10,
58 ETNA_GPU_REGISTER_MAX = 0x11,
59 ETNA_GPU_THREAD_COUNT = 0x12,
60 ETNA_GPU_VERTEX_CACHE_SIZE = 0x13,
61 ETNA_GPU_SHADER_CORE_COUNT = 0x14,
62 ETNA_GPU_PIXEL_PIPES = 0x15,
63 ETNA_GPU_VERTEX_OUTPUT_BUFFER_SIZE = 0x16,
64 ETNA_GPU_BUFFER_SIZE = 0x17,
65 ETNA_GPU_INSTRUCTION_COUNT = 0x18,
66 ETNA_GPU_NUM_CONSTANTS = 0x19,
67 ETNA_GPU_NUM_VARYINGS = 0x1a
68};
69
70/* bo flags: */
71#define DRM_ETNA_GEM_CACHE_CACHED 0x00010000
72#define DRM_ETNA_GEM_CACHE_WC 0x00020000
73#define DRM_ETNA_GEM_CACHE_UNCACHED 0x00040000
74#define DRM_ETNA_GEM_CACHE_MASK 0x000f0000
75/* map flags */
76#define DRM_ETNA_GEM_FORCE_MMU 0x00100000
77
78/* bo access flags: (keep aligned to ETNA_PREP_x) */
79#define DRM_ETNA_PREP_READ 0x01
80#define DRM_ETNA_PREP_WRITE 0x02
81#define DRM_ETNA_PREP_NOSYNC 0x04
82
83/* device functions:
84 */
85
86struct etna_device *etna_device_new(int fd);
87struct etna_device *etna_device_new_dup(int fd);
88struct etna_device *etna_device_ref(struct etna_device *dev);
89void etna_device_del(struct etna_device *dev);
90int etna_device_fd(struct etna_device *dev);
91
92/* gpu functions:
93 */
94
95struct etna_gpu *etna_gpu_new(struct etna_device *dev, unsigned int core);
96void etna_gpu_del(struct etna_gpu *gpu);
97int etna_gpu_get_param(struct etna_gpu *gpu, enum etna_param_id param,
98 uint64_t *value);
99
100
101/* pipe functions:
102 */
103
104struct etna_pipe *etna_pipe_new(struct etna_gpu *gpu, enum etna_pipe_id id);
105void etna_pipe_del(struct etna_pipe *pipe);
106int etna_pipe_wait(struct etna_pipe *pipe, uint32_t timestamp, uint32_t ms);
107int etna_pipe_wait_ns(struct etna_pipe *pipe, uint32_t timestamp, uint64_t ns);
108
109
110/* buffer-object functions:
111 */
112
113struct etna_bo *etna_bo_new(struct etna_device *dev,
114 uint32_t size, uint32_t flags);
115struct etna_bo *etna_bo_from_handle(struct etna_device *dev,
116 uint32_t handle, uint32_t size);
117struct etna_bo *etna_bo_from_name(struct etna_device *dev, uint32_t name);
118struct etna_bo *etna_bo_from_dmabuf(struct etna_device *dev, int fd);
119struct etna_bo *etna_bo_ref(struct etna_bo *bo);
120void etna_bo_del(struct etna_bo *bo);
121int etna_bo_get_name(struct etna_bo *bo, uint32_t *name);
122uint32_t etna_bo_handle(struct etna_bo *bo);
123int etna_bo_dmabuf(struct etna_bo *bo);
124uint32_t etna_bo_size(struct etna_bo *bo);
125void * etna_bo_map(struct etna_bo *bo);
126int etna_bo_cpu_prep(struct etna_bo *bo, uint32_t op);
127void etna_bo_cpu_fini(struct etna_bo *bo);
128
129
130/* cmd stream functions:
131 */
132
133struct etna_cmd_stream {
134 uint32_t *buffer;
135 uint32_t offset; /* in 32-bit words */
136 uint32_t size; /* in 32-bit words */
137};
138
139struct etna_cmd_stream *etna_cmd_stream_new(struct etna_pipe *pipe, uint32_t size,
140 void (*reset_notify)(struct etna_cmd_stream *stream, void *priv),
141 void *priv);
142void etna_cmd_stream_del(struct etna_cmd_stream *stream);
143uint32_t etna_cmd_stream_timestamp(struct etna_cmd_stream *stream);
144void etna_cmd_stream_flush(struct etna_cmd_stream *stream);
145void etna_cmd_stream_finish(struct etna_cmd_stream *stream);
146
147static inline uint32_t etna_cmd_stream_avail(struct etna_cmd_stream *stream)
148{
149 static const uint32_t END_CLEARANCE = 2; /* LINK op code */
150
151 return stream->size - stream->offset - END_CLEARANCE;
152}
153
154static inline void etna_cmd_stream_reserve(struct etna_cmd_stream *stream, size_t n)
155{
156 if (etna_cmd_stream_avail(stream) < n)
157 etna_cmd_stream_flush(stream);
158}
159
160static inline void etna_cmd_stream_emit(struct etna_cmd_stream *stream, uint32_t data)
161{
162 stream->buffer[stream->offset++] = data;
163}
164
165static inline uint32_t etna_cmd_stream_get(struct etna_cmd_stream *stream, uint32_t offset)
166{
167 return stream->buffer[offset];
168}
169
170static inline void etna_cmd_stream_set(struct etna_cmd_stream *stream, uint32_t offset,
171 uint32_t data)
172{
173 stream->buffer[offset] = data;
174}
175
176static inline uint32_t etna_cmd_stream_offset(struct etna_cmd_stream *stream)
177{
178 return stream->offset;
179}
180
181struct etna_reloc {
182 struct etna_bo *bo;
183#define ETNA_RELOC_READ 0x0001
184#define ETNA_RELOC_WRITE 0x0002
185 uint32_t flags;
186 uint32_t offset;
187};
188
189void etna_cmd_stream_reloc(struct etna_cmd_stream *stream, const struct etna_reloc *r);
190
191#endif /* ETNAVIV_DRMIF_H_ */
diff --git a/etnaviv/etnaviv_gpu.c b/etnaviv/etnaviv_gpu.c
new file mode 100644
index 00000000..35dec6cd
--- /dev/null
+++ b/etnaviv/etnaviv_gpu.c
@@ -0,0 +1,175 @@
1/*
2 * Copyright (C) 2015 Etnaviv Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *
23 * Authors:
24 * Christian Gmeiner <christian.gmeiner@gmail.com>
25 */
26
27#ifdef HAVE_CONFIG_H
28# include <config.h>
29#endif
30
31#include "etnaviv_priv.h"
32#include "etnaviv_drmif.h"
33
34static uint64_t get_param(struct etna_device *dev, uint32_t core, uint32_t param)
35{
36 struct drm_etnaviv_param req = {
37 .pipe = core,
38 .param = param,
39 };
40 int ret;
41
42 ret = drmCommandWriteRead(dev->fd, DRM_ETNAVIV_GET_PARAM, &req, sizeof(req));
43 if (ret) {
44 ERROR_MSG("get-param (%x) failed! %d (%s)", param, ret, strerror(errno));
45 return 0;
46 }
47
48 return req.value;
49}
50
51struct etna_gpu *etna_gpu_new(struct etna_device *dev, unsigned int core)
52{
53 struct etna_gpu *gpu;
54
55 gpu = calloc(1, sizeof(*gpu));
56 if (!gpu) {
57 ERROR_MSG("allocation failed");
58 goto fail;
59 }
60
61 gpu->dev = dev;
62 gpu->core = core;
63
64 /* get specs from kernel space */
65 gpu->specs.model = get_param(dev, core, ETNAVIV_PARAM_GPU_MODEL);
66 gpu->specs.revision = get_param(dev, core, ETNAVIV_PARAM_GPU_REVISION);
67 gpu->specs.features[0] = get_param(dev, core, ETNAVIV_PARAM_GPU_FEATURES_0);
68 gpu->specs.features[1] = get_param(dev, core, ETNAVIV_PARAM_GPU_FEATURES_1);
69 gpu->specs.features[2] = get_param(dev, core, ETNAVIV_PARAM_GPU_FEATURES_2);
70 gpu->specs.features[3] = get_param(dev, core, ETNAVIV_PARAM_GPU_FEATURES_3);
71 gpu->specs.features[4] = get_param(dev, core, ETNAVIV_PARAM_GPU_FEATURES_4);
72 gpu->specs.features[5] = get_param(dev, core, ETNAVIV_PARAM_GPU_FEATURES_5);
73 gpu->specs.features[6] = get_param(dev, core, ETNAVIV_PARAM_GPU_FEATURES_6);
74 gpu->specs.stream_count = get_param(dev, core, ETNA_GPU_STREAM_COUNT);
75 gpu->specs.register_max = get_param(dev, core, ETNA_GPU_REGISTER_MAX);
76 gpu->specs.thread_count = get_param(dev, core, ETNA_GPU_THREAD_COUNT);
77 gpu->specs.vertex_cache_size = get_param(dev, core, ETNA_GPU_VERTEX_CACHE_SIZE);
78 gpu->specs.shader_core_count = get_param(dev, core, ETNA_GPU_SHADER_CORE_COUNT);
79 gpu->specs.pixel_pipes = get_param(dev, core, ETNA_GPU_PIXEL_PIPES);
80 gpu->specs.vertex_output_buffer_size = get_param(dev, core, ETNA_GPU_VERTEX_OUTPUT_BUFFER_SIZE);
81 gpu->specs.buffer_size = get_param(dev, core, ETNA_GPU_BUFFER_SIZE);
82 gpu->specs.instruction_count = get_param(dev, core, ETNA_GPU_INSTRUCTION_COUNT);
83 gpu->specs.num_constants = get_param(dev, core, ETNA_GPU_NUM_CONSTANTS);
84 gpu->specs.num_varyings = get_param(dev, core, ETNA_GPU_NUM_VARYINGS);
85
86 if (!gpu->specs.model)
87 goto fail;
88
89 INFO_MSG(" GPU model: 0x%x (rev %x)", gpu->specs.model, gpu->specs.revision);
90
91 return gpu;
92fail:
93 if (gpu)
94 etna_gpu_del(gpu);
95
96 return NULL;
97}
98
99void etna_gpu_del(struct etna_gpu *gpu)
100{
101 free(gpu);
102}
103
104int etna_gpu_get_param(struct etna_gpu *gpu, enum etna_param_id param,
105 uint64_t *value)
106{
107 switch(param) {
108 case ETNA_GPU_MODEL:
109 *value = gpu->specs.model;
110 return 0;
111 case ETNA_GPU_REVISION:
112 *value = gpu->specs.revision;
113 return 0;
114 case ETNA_GPU_FEATURES_0:
115 *value = gpu->specs.features[0];
116 return 0;
117 case ETNA_GPU_FEATURES_1:
118 *value = gpu->specs.features[1];
119 return 0;
120 case ETNA_GPU_FEATURES_2:
121 *value = gpu->specs.features[2];
122 return 0;
123 case ETNA_GPU_FEATURES_3:
124 *value = gpu->specs.features[3];
125 return 0;
126 case ETNA_GPU_FEATURES_4:
127 *value = gpu->specs.features[4];
128 return 0;
129 case ETNA_GPU_FEATURES_5:
130 *value = gpu->specs.features[5];
131 return 0;
132 case ETNA_GPU_FEATURES_6:
133 *value = gpu->specs.features[6];
134 return 0;
135 case ETNA_GPU_STREAM_COUNT:
136 *value = gpu->specs.stream_count;
137 return 0;
138 case ETNA_GPU_REGISTER_MAX:
139 *value = gpu->specs.register_max;
140 return 0;
141 case ETNA_GPU_THREAD_COUNT:
142 *value = gpu->specs.thread_count;
143 return 0;
144 case ETNA_GPU_VERTEX_CACHE_SIZE:
145 *value = gpu->specs.vertex_cache_size;
146 return 0;
147 case ETNA_GPU_SHADER_CORE_COUNT:
148 *value = gpu->specs.shader_core_count;
149 return 0;
150 case ETNA_GPU_PIXEL_PIPES:
151 *value = gpu->specs.pixel_pipes;
152 return 0;
153 case ETNA_GPU_VERTEX_OUTPUT_BUFFER_SIZE:
154 *value = gpu->specs.vertex_output_buffer_size;
155 return 0;
156 case ETNA_GPU_BUFFER_SIZE:
157 *value = gpu->specs.buffer_size;
158 return 0;
159 case ETNA_GPU_INSTRUCTION_COUNT:
160 *value = gpu->specs.instruction_count;
161 return 0;
162 case ETNA_GPU_NUM_CONSTANTS:
163 *value = gpu->specs.num_constants;
164 return 0;
165 case ETNA_GPU_NUM_VARYINGS:
166 *value = gpu->specs.num_varyings;
167 return 0;
168
169 default:
170 ERROR_MSG("invalid param id: %d", param);
171 return -1;
172 }
173
174 return 0;
175}
diff --git a/etnaviv/etnaviv_pipe.c b/etnaviv/etnaviv_pipe.c
new file mode 100644
index 00000000..94c5d377
--- /dev/null
+++ b/etnaviv/etnaviv_pipe.c
@@ -0,0 +1,83 @@
1/*
2 * Copyright (C) 2014-2015 Etnaviv Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *
23 * Authors:
24 * Christian Gmeiner <christian.gmeiner@gmail.com>
25 */
26
27#ifdef HAVE_CONFIG_H
28# include <config.h>
29#endif
30
31#include "etnaviv_priv.h"
32
33int etna_pipe_wait(struct etna_pipe *pipe, uint32_t timestamp, uint32_t ms)
34{
35 return etna_pipe_wait_ns(pipe, timestamp, ms * 1000000);
36}
37
38int etna_pipe_wait_ns(struct etna_pipe *pipe, uint32_t timestamp, uint64_t ns)
39{
40 struct etna_device *dev = pipe->gpu->dev;
41 int ret;
42
43 struct drm_etnaviv_wait_fence req = {
44 .pipe = pipe->gpu->core,
45 .fence = timestamp,
46 };
47
48 if (ns == 0)
49 req.flags |= ETNA_WAIT_NONBLOCK;
50
51 get_abs_timeout(&req.timeout, ns);
52
53 ret = drmCommandWrite(dev->fd, DRM_ETNAVIV_WAIT_FENCE, &req, sizeof(req));
54 if (ret) {
55 ERROR_MSG("wait-fence failed! %d (%s)", ret, strerror(errno));
56 return ret;
57 }
58
59 return 0;
60}
61
62void etna_pipe_del(struct etna_pipe *pipe)
63{
64 free(pipe);
65}
66
67struct etna_pipe *etna_pipe_new(struct etna_gpu *gpu, enum etna_pipe_id id)
68{
69 struct etna_pipe *pipe;
70
71 pipe = calloc(1, sizeof(*pipe));
72 if (!pipe) {
73 ERROR_MSG("allocation failed");
74 goto fail;
75 }
76
77 pipe->id = id;
78 pipe->gpu = gpu;
79
80 return pipe;
81fail:
82 return NULL;
83}
diff --git a/etnaviv/etnaviv_priv.h b/etnaviv/etnaviv_priv.h
new file mode 100644
index 00000000..feaa5ad9
--- /dev/null
+++ b/etnaviv/etnaviv_priv.h
@@ -0,0 +1,201 @@
1/*
2 * Copyright (C) 2014-2015 Etnaviv Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *
23 * Authors:
24 * Christian Gmeiner <christian.gmeiner@gmail.com>
25 */
26
27#ifndef ETNAVIV_PRIV_H_
28#define ETNAVIV_PRIV_H_
29
30#include <stdlib.h>
31#include <errno.h>
32#include <string.h>
33#include <unistd.h>
34#include <errno.h>
35#include <fcntl.h>
36#include <sys/ioctl.h>
37#include <pthread.h>
38#include <stdio.h>
39#include <assert.h>
40
41#include "libdrm_macros.h"
42#include "xf86drm.h"
43#include "xf86atomic.h"
44
45#include "util_double_list.h"
46
47#include "etnaviv_drmif.h"
48#include "etnaviv_drm.h"
49
50#define VIV_FEATURES_WORD_COUNT 7
51
52struct etna_specs {
53 uint32_t model;
54 uint32_t revision;
55 uint32_t features[VIV_FEATURES_WORD_COUNT];
56 uint32_t stream_count;
57 uint32_t register_max;
58 uint32_t thread_count;
59 uint32_t shader_core_count;
60 uint32_t vertex_cache_size;
61 uint32_t vertex_output_buffer_size;
62 uint32_t pixel_pipes;
63 uint32_t instruction_count;
64 uint32_t num_constants;
65 uint32_t num_varyings;
66 uint32_t buffer_size;
67};
68
69struct etna_bo_bucket {
70 uint32_t size;
71 struct list_head list;
72};
73
74struct etna_bo_cache {
75 struct etna_bo_bucket cache_bucket[14 * 4];
76 unsigned num_buckets;
77 time_t time;
78};
79
80struct etna_device {
81 int fd;
82 atomic_t refcnt;
83
84 /* tables to keep track of bo's, to avoid "evil-twin" etna_bo objects:
85 *
86 * handle_table: maps handle to etna_bo
87 * name_table: maps flink name to etna_bo
88 *
89 * We end up needing two tables, because DRM_IOCTL_GEM_OPEN always
90 * returns a new handle. So we need to figure out if the bo is already
91 * open in the process first, before calling gem-open.
92 */
93 void *handle_table, *name_table;
94
95 struct etna_bo_cache bo_cache;
96
97 int closefd; /* call close(fd) upon destruction */
98};
99
100drm_private void etna_bo_cache_init(struct etna_bo_cache *cache);
101drm_private void etna_bo_cache_cleanup(struct etna_bo_cache *cache, time_t time);
102drm_private struct etna_bo *etna_bo_cache_alloc(struct etna_bo_cache *cache,
103 uint32_t *size, uint32_t flags);
104drm_private int etna_bo_cache_free(struct etna_bo_cache *cache, struct etna_bo *bo);
105
106/* for where @table_lock is already held: */
107drm_private void etna_device_del_locked(struct etna_device *dev);
108
109/* a GEM buffer object allocated from the DRM device */
110struct etna_bo {
111 struct etna_device *dev;
112 void *map; /* userspace mmap'ing (if there is one) */
113 uint32_t size;
114 uint32_t handle;
115 uint32_t flags;
116 uint32_t name; /* flink global handle (DRI2 name) */
117 uint64_t offset; /* offset to mmap() */
118 atomic_t refcnt;
119
120 /* in the common case, a bo won't be referenced by more than a single
121 * command stream. So to avoid looping over all the bo's in the
122 * reloc table to find the idx of a bo that might already be in the
123 * table, we cache the idx in the bo. But in order to detect the
124 * slow-path where bo is ref'd in multiple streams, we also must track
125 * the current_stream for which the idx is valid. See bo2idx().
126 */
127 struct etna_cmd_stream *current_stream;
128 uint32_t idx;
129
130 int reuse;
131 struct list_head list; /* bucket-list entry */
132 time_t free_time; /* time when added to bucket-list */
133};
134
135struct etna_gpu {
136 struct etna_device *dev;
137 struct etna_specs specs;
138 uint32_t core;
139};
140
141struct etna_pipe {
142 enum etna_pipe_id id;
143 struct etna_gpu *gpu;
144};
145
146struct etna_cmd_stream_priv {
147 struct etna_cmd_stream base;
148 struct etna_pipe *pipe;
149
150 uint32_t last_timestamp;
151
152 /* submit ioctl related tables: */
153 struct {
154 /* bo's table: */
155 struct drm_etnaviv_gem_submit_bo *bos;
156 uint32_t nr_bos, max_bos;
157
158 /* reloc's table: */
159 struct drm_etnaviv_gem_submit_reloc *relocs;
160 uint32_t nr_relocs, max_relocs;
161 } submit;
162
163 /* should have matching entries in submit.bos: */
164 struct etna_bo **bos;
165 uint32_t nr_bos, max_bos;
166
167 /* notify callback if buffer reset happend */
168 void (*reset_notify)(struct etna_cmd_stream *stream, void *priv);
169 void *reset_notify_priv;
170};
171
172#define ALIGN(v,a) (((v) + (a) - 1) & ~((a) - 1))
173#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
174
175#define enable_debug 1 /* TODO make dynamic */
176
177#define INFO_MSG(fmt, ...) \
178 do { drmMsg("[I] "fmt " (%s:%d)\n", \
179 ##__VA_ARGS__, __FUNCTION__, __LINE__); } while (0)
180#define DEBUG_MSG(fmt, ...) \
181 do if (enable_debug) { drmMsg("[D] "fmt " (%s:%d)\n", \
182 ##__VA_ARGS__, __FUNCTION__, __LINE__); } while (0)
183#define WARN_MSG(fmt, ...) \
184 do { drmMsg("[W] "fmt " (%s:%d)\n", \
185 ##__VA_ARGS__, __FUNCTION__, __LINE__); } while (0)
186#define ERROR_MSG(fmt, ...) \
187 do { drmMsg("[E] " fmt " (%s:%d)\n", \
188 ##__VA_ARGS__, __FUNCTION__, __LINE__); } while (0)
189
190#define VOID2U64(x) ((uint64_t)(unsigned long)(x))
191
192static inline void get_abs_timeout(struct drm_etnaviv_timespec *tv, uint64_t ns)
193{
194 struct timespec t;
195 uint32_t s = ns / 1000000000;
196 clock_gettime(CLOCK_MONOTONIC, &t);
197 tv->tv_sec = t.tv_sec + s;
198 tv->tv_nsec = t.tv_nsec + ns - (s * 1000000000);
199}
200
201#endif /* ETNAVIV_PRIV_H_ */
diff --git a/etnaviv/libdrm_etnaviv.pc.in b/etnaviv/libdrm_etnaviv.pc.in
new file mode 100644
index 00000000..13fed01d
--- /dev/null
+++ b/etnaviv/libdrm_etnaviv.pc.in
@@ -0,0 +1,11 @@
1prefix=@prefix@
2exec_prefix=@exec_prefix@
3libdir=@libdir@
4includedir=@includedir@
5
6Name: libdrm_etnaviv
7Description: Userspace interface to etnaviv kernel DRM services
8Version: @PACKAGE_VERSION@
9Libs: -L${libdir} -ldrm_etnaviv
10Cflags: -I${includedir} -I${includedir}/libdrm
11Requires.private: libdrm
diff --git a/exynos/exynos_drm.c b/exynos/exynos_drm.c
index e689781d..b961e520 100644
--- a/exynos/exynos_drm.c
+++ b/exynos/exynos_drm.c
@@ -347,7 +347,7 @@ exynos_prime_fd_to_handle(struct exynos_device *dev, int fd, uint32_t *handle)
347 * 347 *
348 * @dev: a exynos device object. 348 * @dev: a exynos device object.
349 * @connect: indicate whether connectoin or disconnection request. 349 * @connect: indicate whether connectoin or disconnection request.
350 * @ext: indicate whether edid data includes extentions data or not. 350 * @ext: indicate whether edid data includes extensions data or not.
351 * @edid: a pointer to edid data from Wireless Display device. 351 * @edid: a pointer to edid data from Wireless Display device.
352 * 352 *
353 * this interface is used to request Virtual Display driver connection or 353 * this interface is used to request Virtual Display driver connection or
diff --git a/freedreno/Android.mk b/freedreno/Android.mk
index 162c804a..2b582aed 100644
--- a/freedreno/Android.mk
+++ b/freedreno/Android.mk
@@ -8,9 +8,7 @@ LOCAL_MODULE := libdrm_freedreno
8 8
9LOCAL_SHARED_LIBRARIES := libdrm 9LOCAL_SHARED_LIBRARIES := libdrm
10 10
11LOCAL_SRC_FILES := $(filter-out %.h,$(LIBDRM_FREEDRENO_FILES)) 11LOCAL_SRC_FILES := $(LIBDRM_FREEDRENO_FILES)
12
13LOCAL_CFLAGS := \
14 -DHAVE_LIBDRM_ATOMIC_PRIMITIVES=1
15 12
13include $(LIBDRM_COMMON_MK)
16include $(BUILD_SHARED_LIBRARY) 14include $(BUILD_SHARED_LIBRARY)
diff --git a/freedreno/Makefile.am b/freedreno/Makefile.am
index 9b7ec7df..0771d146 100644
--- a/freedreno/Makefile.am
+++ b/freedreno/Makefile.am
@@ -27,4 +27,4 @@ pkgconfigdir = @pkgconfigdir@
27pkgconfig_DATA = libdrm_freedreno.pc 27pkgconfig_DATA = libdrm_freedreno.pc
28 28
29TESTS = freedreno-symbol-check 29TESTS = freedreno-symbol-check
30EXTRA_DIST = Android.mk $(TESTS) 30EXTRA_DIST = $(TESTS)
diff --git a/freedreno/Makefile.sources b/freedreno/Makefile.sources
index 57a8bf1b..68a679bf 100644
--- a/freedreno/Makefile.sources
+++ b/freedreno/Makefile.sources
@@ -4,6 +4,7 @@ LIBDRM_FREEDRENO_FILES := \
4 freedreno_priv.h \ 4 freedreno_priv.h \
5 freedreno_ringbuffer.c \ 5 freedreno_ringbuffer.c \
6 freedreno_bo.c \ 6 freedreno_bo.c \
7 freedreno_bo_cache.c \
7 msm/msm_bo.c \ 8 msm/msm_bo.c \
8 msm/msm_device.c \ 9 msm/msm_device.c \
9 msm/msm_drm.h \ 10 msm/msm_drm.h \
diff --git a/freedreno/freedreno-symbol-check b/freedreno/freedreno-symbol-check
index f517b6e7..42f2c439 100755
--- a/freedreno/freedreno-symbol-check
+++ b/freedreno/freedreno-symbol-check
@@ -29,22 +29,28 @@ fd_device_fd
29fd_device_new 29fd_device_new
30fd_device_new_dup 30fd_device_new_dup
31fd_device_ref 31fd_device_ref
32fd_device_version
32fd_pipe_del 33fd_pipe_del
33fd_pipe_get_param 34fd_pipe_get_param
34fd_pipe_new 35fd_pipe_new
35fd_pipe_wait 36fd_pipe_wait
36fd_pipe_wait_timeout 37fd_pipe_wait_timeout
38fd_ringbuffer_cmd_count
37fd_ringbuffer_del 39fd_ringbuffer_del
38fd_ringbuffer_emit_reloc_ring 40fd_ringbuffer_emit_reloc_ring
41fd_ringbuffer_emit_reloc_ring_full
39fd_ringbuffer_flush 42fd_ringbuffer_flush
43fd_ringbuffer_grow
40fd_ringbuffer_new 44fd_ringbuffer_new
41fd_ringbuffer_reloc 45fd_ringbuffer_reloc
46fd_ringbuffer_reloc2
42fd_ringbuffer_reset 47fd_ringbuffer_reset
43fd_ringbuffer_set_parent 48fd_ringbuffer_set_parent
44fd_ringbuffer_timestamp 49fd_ringbuffer_timestamp
45fd_ringmarker_del 50fd_ringmarker_del
46fd_ringmarker_dwords 51fd_ringmarker_dwords
47fd_ringmarker_flush 52fd_ringmarker_flush
53fd_ringbuffer_flush2
48fd_ringmarker_mark 54fd_ringmarker_mark
49fd_ringmarker_new 55fd_ringmarker_new
50EOF 56EOF
diff --git a/freedreno/freedreno_bo.c b/freedreno/freedreno_bo.c
index a23c65d0..996d6b95 100644
--- a/freedreno/freedreno_bo.c
+++ b/freedreno/freedreno_bo.c
@@ -33,9 +33,8 @@
33#include "freedreno_drmif.h" 33#include "freedreno_drmif.h"
34#include "freedreno_priv.h" 34#include "freedreno_priv.h"
35 35
36static pthread_mutex_t table_lock = PTHREAD_MUTEX_INITIALIZER; 36drm_private pthread_mutex_t table_lock = PTHREAD_MUTEX_INITIALIZER;
37 37drm_private void bo_del(struct fd_bo *bo);
38static void bo_del(struct fd_bo *bo);
39 38
40/* set buffer name, and add to table, call w/ table_lock held: */ 39/* set buffer name, and add to table, call w/ table_lock held: */
41static void set_name(struct fd_bo *bo, uint32_t name) 40static void set_name(struct fd_bo *bo, uint32_t name)
@@ -83,114 +82,16 @@ static struct fd_bo * bo_from_handle(struct fd_device *dev,
83 return bo; 82 return bo;
84} 83}
85 84
86/* Frees older cached buffers. Called under table_lock */
87drm_private void fd_cleanup_bo_cache(struct fd_device *dev, time_t time)
88{
89 int i;
90
91 if (dev->time == time)
92 return;
93
94 for (i = 0; i < dev->num_buckets; i++) {
95 struct fd_bo_bucket *bucket = &dev->cache_bucket[i];
96 struct fd_bo *bo;
97
98 while (!LIST_IS_EMPTY(&bucket->list)) {
99 bo = LIST_ENTRY(struct fd_bo, bucket->list.next, list);
100
101 /* keep things in cache for at least 1 second: */
102 if (time && ((time - bo->free_time) <= 1))
103 break;
104
105 list_del(&bo->list);
106 bo_del(bo);
107 }
108 }
109
110 dev->time = time;
111}
112
113static struct fd_bo_bucket * get_bucket(struct fd_device *dev, uint32_t size)
114{
115 int i;
116
117 /* hmm, this is what intel does, but I suppose we could calculate our
118 * way to the correct bucket size rather than looping..
119 */
120 for (i = 0; i < dev->num_buckets; i++) {
121 struct fd_bo_bucket *bucket = &dev->cache_bucket[i];
122 if (bucket->size >= size) {
123 return bucket;
124 }
125 }
126
127 return NULL;
128}
129
130static int is_idle(struct fd_bo *bo)
131{
132 return fd_bo_cpu_prep(bo, NULL,
133 DRM_FREEDRENO_PREP_READ |
134 DRM_FREEDRENO_PREP_WRITE |
135 DRM_FREEDRENO_PREP_NOSYNC) == 0;
136}
137
138static struct fd_bo *find_in_bucket(struct fd_device *dev,
139 struct fd_bo_bucket *bucket, uint32_t flags)
140{
141 struct fd_bo *bo = NULL;
142
143 /* TODO .. if we had an ALLOC_FOR_RENDER flag like intel, we could
144 * skip the busy check.. if it is only going to be a render target
145 * then we probably don't need to stall..
146 *
147 * NOTE that intel takes ALLOC_FOR_RENDER bo's from the list tail
148 * (MRU, since likely to be in GPU cache), rather than head (LRU)..
149 */
150 pthread_mutex_lock(&table_lock);
151 while (!LIST_IS_EMPTY(&bucket->list)) {
152 bo = LIST_ENTRY(struct fd_bo, bucket->list.next, list);
153 if (0 /* TODO: if madvise tells us bo is gone... */) {
154 list_del(&bo->list);
155 bo_del(bo);
156 bo = NULL;
157 continue;
158 }
159 /* TODO check for compatible flags? */
160 if (is_idle(bo)) {
161 list_del(&bo->list);
162 break;
163 }
164 bo = NULL;
165 break;
166 }
167 pthread_mutex_unlock(&table_lock);
168
169 return bo;
170}
171
172
173struct fd_bo * 85struct fd_bo *
174fd_bo_new(struct fd_device *dev, uint32_t size, uint32_t flags) 86fd_bo_new(struct fd_device *dev, uint32_t size, uint32_t flags)
175{ 87{
176 struct fd_bo *bo = NULL; 88 struct fd_bo *bo = NULL;
177 struct fd_bo_bucket *bucket;
178 uint32_t handle; 89 uint32_t handle;
179 int ret; 90 int ret;
180 91
181 size = ALIGN(size, 4096); 92 bo = fd_bo_cache_alloc(&dev->bo_cache, &size, flags);
182 bucket = get_bucket(dev, size); 93 if (bo)
183 94 return bo;
184 /* see if we can be green and recycle: */
185 if (bucket) {
186 size = bucket->size;
187 bo = find_in_bucket(dev, bucket, flags);
188 if (bo) {
189 atomic_set(&bo->refcnt, 1);
190 fd_device_ref(bo->dev);
191 return bo;
192 }
193 }
194 95
195 ret = dev->funcs->bo_new_handle(dev, size, flags, &handle); 96 ret = dev->funcs->bo_new_handle(dev, size, flags, &handle);
196 if (ret) 97 if (ret)
@@ -198,7 +99,7 @@ fd_bo_new(struct fd_device *dev, uint32_t size, uint32_t flags)
198 99
199 pthread_mutex_lock(&table_lock); 100 pthread_mutex_lock(&table_lock);
200 bo = bo_from_handle(dev, size, handle); 101 bo = bo_from_handle(dev, size, handle);
201 bo->bo_reuse = 1; 102 bo->bo_reuse = TRUE;
202 pthread_mutex_unlock(&table_lock); 103 pthread_mutex_unlock(&table_lock);
203 104
204 return bo; 105 return bo;
@@ -300,35 +201,17 @@ void fd_bo_del(struct fd_bo *bo)
300 201
301 pthread_mutex_lock(&table_lock); 202 pthread_mutex_lock(&table_lock);
302 203
303 if (bo->bo_reuse) { 204 if (bo->bo_reuse && (fd_bo_cache_free(&dev->bo_cache, bo) == 0))
304 struct fd_bo_bucket *bucket = get_bucket(dev, bo->size); 205 goto out;
305
306 /* see if we can be green and recycle: */
307 if (bucket) {
308 struct timespec time;
309
310 clock_gettime(CLOCK_MONOTONIC, &time);
311
312 bo->free_time = time.tv_sec;
313 list_addtail(&bo->list, &bucket->list);
314 fd_cleanup_bo_cache(dev, time.tv_sec);
315
316 /* bo's in the bucket cache don't have a ref and
317 * don't hold a ref to the dev:
318 */
319
320 goto out;
321 }
322 }
323 206
324 bo_del(bo); 207 bo_del(bo);
325out:
326 fd_device_del_locked(dev); 208 fd_device_del_locked(dev);
209out:
327 pthread_mutex_unlock(&table_lock); 210 pthread_mutex_unlock(&table_lock);
328} 211}
329 212
330/* Called under table_lock */ 213/* Called under table_lock */
331static void bo_del(struct fd_bo *bo) 214drm_private void bo_del(struct fd_bo *bo)
332{ 215{
333 if (bo->map) 216 if (bo->map)
334 drm_munmap(bo->map, bo->size); 217 drm_munmap(bo->map, bo->size);
@@ -366,7 +249,7 @@ int fd_bo_get_name(struct fd_bo *bo, uint32_t *name)
366 pthread_mutex_lock(&table_lock); 249 pthread_mutex_lock(&table_lock);
367 set_name(bo, req.name); 250 set_name(bo, req.name);
368 pthread_mutex_unlock(&table_lock); 251 pthread_mutex_unlock(&table_lock);
369 bo->bo_reuse = 0; 252 bo->bo_reuse = FALSE;
370 } 253 }
371 254
372 *name = bo->name; 255 *name = bo->name;
@@ -390,7 +273,7 @@ int fd_bo_dmabuf(struct fd_bo *bo)
390 return ret; 273 return ret;
391 } 274 }
392 275
393 bo->bo_reuse = 0; 276 bo->bo_reuse = FALSE;
394 277
395 return prime_fd; 278 return prime_fd;
396} 279}
@@ -431,3 +314,10 @@ void fd_bo_cpu_fini(struct fd_bo *bo)
431{ 314{
432 bo->funcs->cpu_fini(bo); 315 bo->funcs->cpu_fini(bo);
433} 316}
317
318#ifndef HAVE_FREEDRENO_KGSL
319struct fd_bo * fd_bo_from_fbdev(struct fd_pipe *pipe, int fbfd, uint32_t size)
320{
321 return NULL;
322}
323#endif
diff --git a/freedreno/freedreno_bo_cache.c b/freedreno/freedreno_bo_cache.c
new file mode 100644
index 00000000..7becb0d6
--- /dev/null
+++ b/freedreno/freedreno_bo_cache.c
@@ -0,0 +1,222 @@
1/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
2
3/*
4 * Copyright (C) 2016 Rob Clark <robclark@freedesktop.org>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 *
25 * Authors:
26 * Rob Clark <robclark@freedesktop.org>
27 */
28
29#ifdef HAVE_CONFIG_H
30# include <config.h>
31#endif
32
33#include "freedreno_drmif.h"
34#include "freedreno_priv.h"
35
36
37drm_private void bo_del(struct fd_bo *bo);
38drm_private extern pthread_mutex_t table_lock;
39
40static void
41add_bucket(struct fd_bo_cache *cache, int size)
42{
43 unsigned int i = cache->num_buckets;
44
45 assert(i < ARRAY_SIZE(cache->cache_bucket));
46
47 list_inithead(&cache->cache_bucket[i].list);
48 cache->cache_bucket[i].size = size;
49 cache->num_buckets++;
50}
51
52/**
53 * @coarse: if true, only power-of-two bucket sizes, otherwise
54 * fill in for a bit smoother size curve..
55 */
56drm_private void
57fd_bo_cache_init(struct fd_bo_cache *cache, int course)
58{
59 unsigned long size, cache_max_size = 64 * 1024 * 1024;
60
61 /* OK, so power of two buckets was too wasteful of memory.
62 * Give 3 other sizes between each power of two, to hopefully
63 * cover things accurately enough. (The alternative is
64 * probably to just go for exact matching of sizes, and assume
65 * that for things like composited window resize the tiled
66 * width/height alignment and rounding of sizes to pages will
67 * get us useful cache hit rates anyway)
68 */
69 add_bucket(cache, 4096);
70 add_bucket(cache, 4096 * 2);
71 if (!course)
72 add_bucket(cache, 4096 * 3);
73
74 /* Initialize the linked lists for BO reuse cache. */
75 for (size = 4 * 4096; size <= cache_max_size; size *= 2) {
76 add_bucket(cache, size);
77 if (!course) {
78 add_bucket(cache, size + size * 1 / 4);
79 add_bucket(cache, size + size * 2 / 4);
80 add_bucket(cache, size + size * 3 / 4);
81 }
82 }
83}
84
85/* Frees older cached buffers. Called under table_lock */
86drm_private void
87fd_bo_cache_cleanup(struct fd_bo_cache *cache, time_t time)
88{
89 int i;
90
91 if (cache->time == time)
92 return;
93
94 for (i = 0; i < cache->num_buckets; i++) {
95 struct fd_bo_bucket *bucket = &cache->cache_bucket[i];
96 struct fd_bo *bo;