aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/radeon_kms.c
diff options
context:
space:
mode:
authorJerome Glisse <jglisse@redhat.com>2009-06-05 08:42:42 -0400
committerDave Airlie <airlied@redhat.com>2009-06-14 22:01:53 -0400
commit771fe6b912fca54f03e8a72eb63058b582775362 (patch)
tree58aa5469ba8058c2b564d50807395ad6cd7bd7e4 /drivers/gpu/drm/radeon/radeon_kms.c
parentba4e7d973dd09b66912ac4c0856add8b0703a997 (diff)
drm/radeon: introduce kernel modesetting for radeon hardware
Add kernel modesetting support to radeon driver, use the ttm memory manager to manage memory and DRM/GEM to provide userspace API. In order to avoid backward compatibility issue and to allow clean design and code the radeon kernel modesetting use different code path than old radeon/drm driver. When kernel modesetting is enabled the IOCTL of radeon/drm driver are considered as invalid and an error message is printed in the log and they return failure. KMS enabled userspace will use new API to talk with the radeon/drm driver. The new API provide functions to create/destroy/share/mmap buffer object which are then managed by the kernel memory manager (here TTM). In order to submit command to the GPU the userspace provide a buffer holding the command stream, along this buffer userspace have to provide a list of buffer object used by the command stream. The kernel radeon driver will then place buffer in GPU accessible memory and will update command stream to reflect the position of the different buffers. The kernel will also perform security check on command stream provided by the user, we want to catch and forbid any illegal use of the GPU such as DMA into random system memory or into memory not owned by the process supplying the command stream. This part of the code is still incomplete and this why we propose that patch as a staging driver addition, future security might forbid current experimental userspace to run. This code support the following hardware : R1XX,R2XX,R3XX,R4XX,R5XX (radeon up to X1950). Works is underway to provide support for R6XX, R7XX and newer hardware (radeon from HD2XXX to HD4XXX). Authors: Jerome Glisse <jglisse@redhat.com> Dave Airlie <airlied@redhat.com> Alex Deucher <alexdeucher@gmail.com> Signed-off-by: Jerome Glisse <jglisse@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> Signed-off-by: Alex Deucher <alexdeucher@gmail.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_kms.c')
-rw-r--r--drivers/gpu/drm/radeon/radeon_kms.c295
1 files changed, 295 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
new file mode 100644
index 000000000000..b0ce44b9f5ab
--- /dev/null
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -0,0 +1,295 @@
1/*
2 * Copyright 2008 Advanced Micro Devices, Inc.
3 * Copyright 2008 Red Hat Inc.
4 * Copyright 2009 Jerome Glisse.
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 shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Authors: Dave Airlie
25 * Alex Deucher
26 * Jerome Glisse
27 */
28#include "drmP.h"
29#include "drm_sarea.h"
30#include "radeon.h"
31#include "radeon_drm.h"
32
33
34/*
35 * Driver load/unload
36 */
37int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags)
38{
39 struct radeon_device *rdev;
40 int r;
41
42 rdev = kzalloc(sizeof(struct radeon_device), GFP_KERNEL);
43 if (rdev == NULL) {
44 return -ENOMEM;
45 }
46 dev->dev_private = (void *)rdev;
47
48 /* update BUS flag */
49 if (drm_device_is_agp(dev)) {
50 flags |= RADEON_IS_AGP;
51 } else if (drm_device_is_pcie(dev)) {
52 flags |= RADEON_IS_PCIE;
53 } else {
54 flags |= RADEON_IS_PCI;
55 }
56
57 r = radeon_device_init(rdev, dev, dev->pdev, flags);
58 if (r) {
59 DRM_ERROR("Failed to initialize radeon, disabling IOCTL\n");
60 radeon_device_fini(rdev);
61 return r;
62 }
63 return 0;
64}
65
66int radeon_driver_unload_kms(struct drm_device *dev)
67{
68 struct radeon_device *rdev = dev->dev_private;
69
70 radeon_device_fini(rdev);
71 kfree(rdev);
72 dev->dev_private = NULL;
73 return 0;
74}
75
76
77/*
78 * Userspace get informations ioctl
79 */
80int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
81{
82 struct radeon_device *rdev = dev->dev_private;
83 struct drm_radeon_info *info;
84 uint32_t *value_ptr;
85 uint32_t value;
86
87 info = data;
88 value_ptr = (uint32_t *)((unsigned long)info->value);
89 switch (info->request) {
90 case RADEON_INFO_DEVICE_ID:
91 value = dev->pci_device;
92 break;
93 case RADEON_INFO_NUM_GB_PIPES:
94 value = rdev->num_gb_pipes;
95 break;
96 default:
97 DRM_DEBUG("Invalid request %d\n", info->request);
98 return -EINVAL;
99 }
100 if (DRM_COPY_TO_USER(value_ptr, &value, sizeof(uint32_t))) {
101 DRM_ERROR("copy_to_user\n");
102 return -EFAULT;
103 }
104 return 0;
105}
106
107
108/*
109 * Outdated mess for old drm with Xorg being in charge (void function now).
110 */
111int radeon_driver_firstopen_kms(struct drm_device *dev)
112{
113 return 0;
114}
115
116
117void radeon_driver_lastclose_kms(struct drm_device *dev)
118{
119}
120
121int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
122{
123 return 0;
124}
125
126void radeon_driver_postclose_kms(struct drm_device *dev,
127 struct drm_file *file_priv)
128{
129}
130
131void radeon_driver_preclose_kms(struct drm_device *dev,
132 struct drm_file *file_priv)
133{
134}
135
136
137/*
138 * VBlank related functions.
139 */
140u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc)
141{
142 /* FIXME: implement */
143 return 0;
144}
145
146int radeon_enable_vblank_kms(struct drm_device *dev, int crtc)
147{
148 /* FIXME: implement */
149 return 0;
150}
151
152void radeon_disable_vblank_kms(struct drm_device *dev, int crtc)
153{
154 /* FIXME: implement */
155}
156
157
158/*
159 * For multiple master (like multiple X).
160 */
161struct drm_radeon_master_private {
162 drm_local_map_t *sarea;
163 drm_radeon_sarea_t *sarea_priv;
164};
165
166int radeon_master_create_kms(struct drm_device *dev, struct drm_master *master)
167{
168 struct drm_radeon_master_private *master_priv;
169 unsigned long sareapage;
170 int ret;
171
172 master_priv = drm_calloc(1, sizeof(*master_priv), DRM_MEM_DRIVER);
173 if (master_priv == NULL) {
174 return -ENOMEM;
175 }
176 /* prebuild the SAREA */
177 sareapage = max_t(unsigned long, SAREA_MAX, PAGE_SIZE);
178 ret = drm_addmap(dev, 0, sareapage, _DRM_SHM,
179 _DRM_CONTAINS_LOCK|_DRM_DRIVER,
180 &master_priv->sarea);
181 if (ret) {
182 DRM_ERROR("SAREA setup failed\n");
183 return ret;
184 }
185 master_priv->sarea_priv = master_priv->sarea->handle + sizeof(struct drm_sarea);
186 master_priv->sarea_priv->pfCurrentPage = 0;
187 master->driver_priv = master_priv;
188 return 0;
189}
190
191void radeon_master_destroy_kms(struct drm_device *dev,
192 struct drm_master *master)
193{
194 struct drm_radeon_master_private *master_priv = master->driver_priv;
195
196 if (master_priv == NULL) {
197 return;
198 }
199 if (master_priv->sarea) {
200 drm_rmmap_locked(dev, master_priv->sarea);
201 }
202 drm_free(master_priv, sizeof(*master_priv), DRM_MEM_DRIVER);
203 master->driver_priv = NULL;
204}
205
206
207/*
208 * IOCTL.
209 */
210int radeon_dma_ioctl_kms(struct drm_device *dev, void *data,
211 struct drm_file *file_priv)
212{
213 /* Not valid in KMS. */
214 return -EINVAL;
215}
216
217#define KMS_INVALID_IOCTL(name) \
218int name(struct drm_device *dev, void *data, struct drm_file *file_priv)\
219{ \
220 DRM_ERROR("invalid ioctl with kms %s\n", __func__); \
221 return -EINVAL; \
222}
223
224/*
225 * All these ioctls are invalid in kms world.
226 */
227KMS_INVALID_IOCTL(radeon_cp_init_kms)
228KMS_INVALID_IOCTL(radeon_cp_start_kms)
229KMS_INVALID_IOCTL(radeon_cp_stop_kms)
230KMS_INVALID_IOCTL(radeon_cp_reset_kms)
231KMS_INVALID_IOCTL(radeon_cp_idle_kms)
232KMS_INVALID_IOCTL(radeon_cp_resume_kms)
233KMS_INVALID_IOCTL(radeon_engine_reset_kms)
234KMS_INVALID_IOCTL(radeon_fullscreen_kms)
235KMS_INVALID_IOCTL(radeon_cp_swap_kms)
236KMS_INVALID_IOCTL(radeon_cp_clear_kms)
237KMS_INVALID_IOCTL(radeon_cp_vertex_kms)
238KMS_INVALID_IOCTL(radeon_cp_indices_kms)
239KMS_INVALID_IOCTL(radeon_cp_texture_kms)
240KMS_INVALID_IOCTL(radeon_cp_stipple_kms)
241KMS_INVALID_IOCTL(radeon_cp_indirect_kms)
242KMS_INVALID_IOCTL(radeon_cp_vertex2_kms)
243KMS_INVALID_IOCTL(radeon_cp_cmdbuf_kms)
244KMS_INVALID_IOCTL(radeon_cp_getparam_kms)
245KMS_INVALID_IOCTL(radeon_cp_flip_kms)
246KMS_INVALID_IOCTL(radeon_mem_alloc_kms)
247KMS_INVALID_IOCTL(radeon_mem_free_kms)
248KMS_INVALID_IOCTL(radeon_mem_init_heap_kms)
249KMS_INVALID_IOCTL(radeon_irq_emit_kms)
250KMS_INVALID_IOCTL(radeon_irq_wait_kms)
251KMS_INVALID_IOCTL(radeon_cp_setparam_kms)
252KMS_INVALID_IOCTL(radeon_surface_alloc_kms)
253KMS_INVALID_IOCTL(radeon_surface_free_kms)
254
255
256struct drm_ioctl_desc radeon_ioctls_kms[] = {
257 DRM_IOCTL_DEF(DRM_RADEON_CP_INIT, radeon_cp_init_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
258 DRM_IOCTL_DEF(DRM_RADEON_CP_START, radeon_cp_start_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
259 DRM_IOCTL_DEF(DRM_RADEON_CP_STOP, radeon_cp_stop_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
260 DRM_IOCTL_DEF(DRM_RADEON_CP_RESET, radeon_cp_reset_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
261 DRM_IOCTL_DEF(DRM_RADEON_CP_IDLE, radeon_cp_idle_kms, DRM_AUTH),
262 DRM_IOCTL_DEF(DRM_RADEON_CP_RESUME, radeon_cp_resume_kms, DRM_AUTH),
263 DRM_IOCTL_DEF(DRM_RADEON_RESET, radeon_engine_reset_kms, DRM_AUTH),
264 DRM_IOCTL_DEF(DRM_RADEON_FULLSCREEN, radeon_fullscreen_kms, DRM_AUTH),
265 DRM_IOCTL_DEF(DRM_RADEON_SWAP, radeon_cp_swap_kms, DRM_AUTH),
266 DRM_IOCTL_DEF(DRM_RADEON_CLEAR, radeon_cp_clear_kms, DRM_AUTH),
267 DRM_IOCTL_DEF(DRM_RADEON_VERTEX, radeon_cp_vertex_kms, DRM_AUTH),
268 DRM_IOCTL_DEF(DRM_RADEON_INDICES, radeon_cp_indices_kms, DRM_AUTH),
269 DRM_IOCTL_DEF(DRM_RADEON_TEXTURE, radeon_cp_texture_kms, DRM_AUTH),
270 DRM_IOCTL_DEF(DRM_RADEON_STIPPLE, radeon_cp_stipple_kms, DRM_AUTH),
271 DRM_IOCTL_DEF(DRM_RADEON_INDIRECT, radeon_cp_indirect_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
272 DRM_IOCTL_DEF(DRM_RADEON_VERTEX2, radeon_cp_vertex2_kms, DRM_AUTH),
273 DRM_IOCTL_DEF(DRM_RADEON_CMDBUF, radeon_cp_cmdbuf_kms, DRM_AUTH),
274 DRM_IOCTL_DEF(DRM_RADEON_GETPARAM, radeon_cp_getparam_kms, DRM_AUTH),
275 DRM_IOCTL_DEF(DRM_RADEON_FLIP, radeon_cp_flip_kms, DRM_AUTH),
276 DRM_IOCTL_DEF(DRM_RADEON_ALLOC, radeon_mem_alloc_kms, DRM_AUTH),
277 DRM_IOCTL_DEF(DRM_RADEON_FREE, radeon_mem_free_kms, DRM_AUTH),
278 DRM_IOCTL_DEF(DRM_RADEON_INIT_HEAP, radeon_mem_init_heap_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
279 DRM_IOCTL_DEF(DRM_RADEON_IRQ_EMIT, radeon_irq_emit_kms, DRM_AUTH),
280 DRM_IOCTL_DEF(DRM_RADEON_IRQ_WAIT, radeon_irq_wait_kms, DRM_AUTH),
281 DRM_IOCTL_DEF(DRM_RADEON_SETPARAM, radeon_cp_setparam_kms, DRM_AUTH),
282 DRM_IOCTL_DEF(DRM_RADEON_SURF_ALLOC, radeon_surface_alloc_kms, DRM_AUTH),
283 DRM_IOCTL_DEF(DRM_RADEON_SURF_FREE, radeon_surface_free_kms, DRM_AUTH),
284 /* KMS */
285 DRM_IOCTL_DEF(DRM_RADEON_GEM_INFO, radeon_gem_info_ioctl, DRM_AUTH),
286 DRM_IOCTL_DEF(DRM_RADEON_GEM_CREATE, radeon_gem_create_ioctl, DRM_AUTH),
287 DRM_IOCTL_DEF(DRM_RADEON_GEM_MMAP, radeon_gem_mmap_ioctl, DRM_AUTH),
288 DRM_IOCTL_DEF(DRM_RADEON_GEM_SET_DOMAIN, radeon_gem_set_domain_ioctl, DRM_AUTH),
289 DRM_IOCTL_DEF(DRM_RADEON_GEM_PREAD, radeon_gem_pread_ioctl, DRM_AUTH),
290 DRM_IOCTL_DEF(DRM_RADEON_GEM_PWRITE, radeon_gem_pwrite_ioctl, DRM_AUTH),
291 DRM_IOCTL_DEF(DRM_RADEON_GEM_WAIT_IDLE, radeon_gem_wait_idle_ioctl, DRM_AUTH),
292 DRM_IOCTL_DEF(DRM_RADEON_CS, radeon_cs_ioctl, DRM_AUTH),
293 DRM_IOCTL_DEF(DRM_RADEON_INFO, radeon_info_ioctl, DRM_AUTH),
294};
295int radeon_max_kms_ioctl = DRM_ARRAY_SIZE(radeon_ioctls_kms);