2 * Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com
4 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
8 * Author Rickard E. (Rik) Faith <faith@valinux.com>
9 * Author Gareth Hughes <gareth@valinux.com>
11 * Permission is hereby granted, free of charge, to any person obtaining a
12 * copy of this software and associated documentation files (the "Software"),
13 * to deal in the Software without restriction, including without limitation
14 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 * and/or sell copies of the Software, and to permit persons to whom the
16 * Software is furnished to do so, subject to the following conditions:
18 * The above copyright notice and this permission notice (including the next
19 * paragraph) shall be included in all copies or substantial portions of the
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
26 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
27 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 * OTHER DEALINGS IN THE SOFTWARE.
32 #include "drm_internal.h"
33 #include "drm_legacy.h"
36 * drm_getmagic - Get unique magic of a client
37 * @dev: DRM device to operate on
38 * @data: ioctl data containing the drm_auth object
39 * @file_priv: DRM file that performs the operation
41 * This looks up the unique magic of the passed client and returns it. If the
42 * client did not have a magic assigned, yet, a new one is registered. The magic
43 * is stored in the passed drm_auth object.
45 * Returns: 0 on success, negative error code on failure.
47 int drm_getmagic(struct drm_device
*dev
, void *data
, struct drm_file
*file_priv
)
49 struct drm_auth
*auth
= data
;
52 mutex_lock(&dev
->struct_mutex
);
53 if (!file_priv
->magic
) {
54 ret
= idr_alloc(&file_priv
->master
->magic_map
, file_priv
,
57 file_priv
->magic
= ret
;
59 auth
->magic
= file_priv
->magic
;
60 mutex_unlock(&dev
->struct_mutex
);
62 DRM_DEBUG("%u\n", auth
->magic
);
64 return ret
< 0 ? ret
: 0;
68 * drm_authmagic - Authenticate client with a magic
69 * @dev: DRM device to operate on
70 * @data: ioctl data containing the drm_auth object
71 * @file_priv: DRM file that performs the operation
73 * This looks up a DRM client by the passed magic and authenticates it.
75 * Returns: 0 on success, negative error code on failure.
77 int drm_authmagic(struct drm_device
*dev
, void *data
,
78 struct drm_file
*file_priv
)
80 struct drm_auth
*auth
= data
;
81 struct drm_file
*file
;
83 DRM_DEBUG("%u\n", auth
->magic
);
85 mutex_lock(&dev
->struct_mutex
);
86 file
= idr_find(&file_priv
->master
->magic_map
, auth
->magic
);
88 file
->authenticated
= 1;
89 idr_replace(&file_priv
->master
->magic_map
, NULL
, auth
->magic
);
91 mutex_unlock(&dev
->struct_mutex
);
93 return file
? 0 : -EINVAL
;
96 static struct drm_master
*drm_master_create(struct drm_device
*dev
)
98 struct drm_master
*master
;
100 master
= kzalloc(sizeof(*master
), GFP_KERNEL
);
104 kref_init(&master
->refcount
);
105 spin_lock_init(&master
->lock
.spinlock
);
106 init_waitqueue_head(&master
->lock
.lock_queue
);
107 idr_init(&master
->magic_map
);
114 * drm_new_set_master - Allocate a new master object and become master for the
115 * associated master realm.
117 * @dev: The associated device.
118 * @fpriv: File private identifying the client.
120 * This function must be called with dev::struct_mutex held.
121 * Returns negative error code on failure. Zero on success.
123 static int drm_new_set_master(struct drm_device
*dev
, struct drm_file
*fpriv
)
125 struct drm_master
*old_master
;
128 lockdep_assert_held_once(&dev
->master_mutex
);
130 /* create a new master */
131 fpriv
->minor
->master
= drm_master_create(fpriv
->minor
->dev
);
132 if (!fpriv
->minor
->master
)
135 /* take another reference for the copy in the local file priv */
136 old_master
= fpriv
->master
;
137 fpriv
->master
= drm_master_get(fpriv
->minor
->master
);
139 if (dev
->driver
->master_create
) {
140 ret
= dev
->driver
->master_create(dev
, fpriv
->master
);
144 if (dev
->driver
->master_set
) {
145 ret
= dev
->driver
->master_set(dev
, fpriv
, true);
150 fpriv
->is_master
= 1;
151 fpriv
->allowed_master
= 1;
152 fpriv
->authenticated
= 1;
154 drm_master_put(&old_master
);
159 /* drop both references and restore old master on failure */
160 drm_master_put(&fpriv
->minor
->master
);
161 drm_master_put(&fpriv
->master
);
162 fpriv
->master
= old_master
;
167 int drm_setmaster_ioctl(struct drm_device
*dev
, void *data
,
168 struct drm_file
*file_priv
)
172 mutex_lock(&dev
->master_mutex
);
173 if (file_priv
->is_master
)
176 if (file_priv
->minor
->master
) {
181 if (!file_priv
->master
) {
186 if (!file_priv
->allowed_master
) {
187 ret
= drm_new_set_master(dev
, file_priv
);
191 file_priv
->minor
->master
= drm_master_get(file_priv
->master
);
192 file_priv
->is_master
= 1;
193 if (dev
->driver
->master_set
) {
194 ret
= dev
->driver
->master_set(dev
, file_priv
, false);
195 if (unlikely(ret
!= 0)) {
196 file_priv
->is_master
= 0;
197 drm_master_put(&file_priv
->minor
->master
);
202 mutex_unlock(&dev
->master_mutex
);
206 int drm_dropmaster_ioctl(struct drm_device
*dev
, void *data
,
207 struct drm_file
*file_priv
)
211 mutex_lock(&dev
->master_mutex
);
212 if (!file_priv
->is_master
)
215 if (!file_priv
->minor
->master
)
219 if (dev
->driver
->master_drop
)
220 dev
->driver
->master_drop(dev
, file_priv
, false);
221 drm_master_put(&file_priv
->minor
->master
);
222 file_priv
->is_master
= 0;
225 mutex_unlock(&dev
->master_mutex
);
229 int drm_master_open(struct drm_file
*file_priv
)
231 struct drm_device
*dev
= file_priv
->minor
->dev
;
234 /* if there is no current master make this fd it, but do not create
235 * any master object for render clients */
236 mutex_lock(&dev
->master_mutex
);
237 if (!file_priv
->minor
->master
)
238 ret
= drm_new_set_master(dev
, file_priv
);
240 file_priv
->master
= drm_master_get(file_priv
->minor
->master
);
241 mutex_unlock(&dev
->master_mutex
);
246 void drm_master_release(struct drm_file
*file_priv
)
248 struct drm_device
*dev
= file_priv
->minor
->dev
;
249 struct drm_master
*master
= file_priv
->master
;
251 mutex_lock(&dev
->struct_mutex
);
252 if (file_priv
->magic
)
253 idr_remove(&file_priv
->master
->magic_map
, file_priv
->magic
);
254 mutex_unlock(&dev
->struct_mutex
);
256 mutex_lock(&dev
->master_mutex
);
257 if (!file_priv
->is_master
)
260 if (!drm_core_check_feature(dev
, DRIVER_MODESET
)) {
262 * Since the master is disappearing, so is the
263 * possibility to lock.
265 mutex_lock(&dev
->struct_mutex
);
266 if (master
->lock
.hw_lock
) {
267 if (dev
->sigdata
.lock
== master
->lock
.hw_lock
)
268 dev
->sigdata
.lock
= NULL
;
269 master
->lock
.hw_lock
= NULL
;
270 master
->lock
.file_priv
= NULL
;
271 wake_up_interruptible_all(&master
->lock
.lock_queue
);
273 mutex_unlock(&dev
->struct_mutex
);
276 if (file_priv
->minor
->master
== file_priv
->master
) {
277 /* drop the reference held my the minor */
278 if (dev
->driver
->master_drop
)
279 dev
->driver
->master_drop(dev
, file_priv
, true);
280 drm_master_put(&file_priv
->minor
->master
);
283 /* drop the master reference held by the file priv */
284 if (file_priv
->master
)
285 drm_master_put(&file_priv
->master
);
286 file_priv
->is_master
= 0;
287 mutex_unlock(&dev
->master_mutex
);
290 struct drm_master
*drm_master_get(struct drm_master
*master
)
292 kref_get(&master
->refcount
);
295 EXPORT_SYMBOL(drm_master_get
);
297 static void drm_master_destroy(struct kref
*kref
)
299 struct drm_master
*master
= container_of(kref
, struct drm_master
, refcount
);
300 struct drm_device
*dev
= master
->dev
;
302 if (dev
->driver
->master_destroy
)
303 dev
->driver
->master_destroy(dev
, master
);
305 drm_legacy_master_rmmaps(dev
, master
);
307 idr_destroy(&master
->magic_map
);
308 kfree(master
->unique
);
312 void drm_master_put(struct drm_master
**master
)
314 kref_put(&(*master
)->refcount
, drm_master_destroy
);
317 EXPORT_SYMBOL(drm_master_put
);
This page took 0.039842 seconds and 6 git commands to generate.