diff options
Diffstat (limited to 'drivers/gpu/drm/drm_auth.c')
-rw-r--r-- | drivers/gpu/drm/drm_auth.c | 178 |
1 files changed, 35 insertions, 143 deletions
diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c index fc8e8aaa34fb..50d0baa06db0 100644 --- a/drivers/gpu/drm/drm_auth.c +++ b/drivers/gpu/drm/drm_auth.c | |||
@@ -1,11 +1,3 @@ | |||
1 | /** | ||
2 | * \file drm_auth.c | ||
3 | * IOCTLs for authentication | ||
4 | * | ||
5 | * \author Rickard E. (Rik) Faith <faith@valinux.com> | ||
6 | * \author Gareth Hughes <gareth@valinux.com> | ||
7 | */ | ||
8 | |||
9 | /* | 1 | /* |
10 | * Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com | 2 | * Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com |
11 | * | 3 | * |
@@ -13,6 +5,9 @@ | |||
13 | * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. | 5 | * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. |
14 | * All Rights Reserved. | 6 | * All Rights Reserved. |
15 | * | 7 | * |
8 | * Author Rickard E. (Rik) Faith <faith@valinux.com> | ||
9 | * Author Gareth Hughes <gareth@valinux.com> | ||
10 | * | ||
16 | * Permission is hereby granted, free of charge, to any person obtaining a | 11 | * Permission is hereby granted, free of charge, to any person obtaining a |
17 | * copy of this software and associated documentation files (the "Software"), | 12 | * copy of this software and associated documentation files (the "Software"), |
18 | * to deal in the Software without restriction, including without limitation | 13 | * to deal in the Software without restriction, including without limitation |
@@ -36,154 +31,47 @@ | |||
36 | #include <drm/drmP.h> | 31 | #include <drm/drmP.h> |
37 | #include "drm_internal.h" | 32 | #include "drm_internal.h" |
38 | 33 | ||
39 | struct drm_magic_entry { | ||
40 | struct list_head head; | ||
41 | struct drm_hash_item hash_item; | ||
42 | struct drm_file *priv; | ||
43 | }; | ||
44 | |||
45 | /** | ||
46 | * Find the file with the given magic number. | ||
47 | * | ||
48 | * \param dev DRM device. | ||
49 | * \param magic magic number. | ||
50 | * | ||
51 | * Searches in drm_device::magiclist within all files with the same hash key | ||
52 | * the one with matching magic number, while holding the drm_device::struct_mutex | ||
53 | * lock. | ||
54 | */ | ||
55 | static struct drm_file *drm_find_file(struct drm_master *master, drm_magic_t magic) | ||
56 | { | ||
57 | struct drm_file *retval = NULL; | ||
58 | struct drm_magic_entry *pt; | ||
59 | struct drm_hash_item *hash; | ||
60 | struct drm_device *dev = master->minor->dev; | ||
61 | |||
62 | mutex_lock(&dev->struct_mutex); | ||
63 | if (!drm_ht_find_item(&master->magiclist, (unsigned long)magic, &hash)) { | ||
64 | pt = drm_hash_entry(hash, struct drm_magic_entry, hash_item); | ||
65 | retval = pt->priv; | ||
66 | } | ||
67 | mutex_unlock(&dev->struct_mutex); | ||
68 | return retval; | ||
69 | } | ||
70 | |||
71 | /** | ||
72 | * Adds a magic number. | ||
73 | * | ||
74 | * \param dev DRM device. | ||
75 | * \param priv file private data. | ||
76 | * \param magic magic number. | ||
77 | * | ||
78 | * Creates a drm_magic_entry structure and appends to the linked list | ||
79 | * associated the magic number hash key in drm_device::magiclist, while holding | ||
80 | * the drm_device::struct_mutex lock. | ||
81 | */ | ||
82 | static int drm_add_magic(struct drm_master *master, struct drm_file *priv, | ||
83 | drm_magic_t magic) | ||
84 | { | ||
85 | struct drm_magic_entry *entry; | ||
86 | struct drm_device *dev = master->minor->dev; | ||
87 | DRM_DEBUG("%d\n", magic); | ||
88 | |||
89 | entry = kzalloc(sizeof(*entry), GFP_KERNEL); | ||
90 | if (!entry) | ||
91 | return -ENOMEM; | ||
92 | entry->priv = priv; | ||
93 | entry->hash_item.key = (unsigned long)magic; | ||
94 | mutex_lock(&dev->struct_mutex); | ||
95 | drm_ht_insert_item(&master->magiclist, &entry->hash_item); | ||
96 | list_add_tail(&entry->head, &master->magicfree); | ||
97 | mutex_unlock(&dev->struct_mutex); | ||
98 | |||
99 | return 0; | ||
100 | } | ||
101 | |||
102 | /** | ||
103 | * Remove a magic number. | ||
104 | * | ||
105 | * \param dev DRM device. | ||
106 | * \param magic magic number. | ||
107 | * | ||
108 | * Searches and unlinks the entry in drm_device::magiclist with the magic | ||
109 | * number hash key, while holding the drm_device::struct_mutex lock. | ||
110 | */ | ||
111 | int drm_remove_magic(struct drm_master *master, drm_magic_t magic) | ||
112 | { | ||
113 | struct drm_magic_entry *pt; | ||
114 | struct drm_hash_item *hash; | ||
115 | struct drm_device *dev = master->minor->dev; | ||
116 | |||
117 | DRM_DEBUG("%d\n", magic); | ||
118 | |||
119 | mutex_lock(&dev->struct_mutex); | ||
120 | if (drm_ht_find_item(&master->magiclist, (unsigned long)magic, &hash)) { | ||
121 | mutex_unlock(&dev->struct_mutex); | ||
122 | return -EINVAL; | ||
123 | } | ||
124 | pt = drm_hash_entry(hash, struct drm_magic_entry, hash_item); | ||
125 | drm_ht_remove_item(&master->magiclist, hash); | ||
126 | list_del(&pt->head); | ||
127 | mutex_unlock(&dev->struct_mutex); | ||
128 | |||
129 | kfree(pt); | ||
130 | |||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | /** | 34 | /** |
135 | * Get a unique magic number (ioctl). | 35 | * drm_getmagic - Get unique magic of a client |
36 | * @dev: DRM device to operate on | ||
37 | * @data: ioctl data containing the drm_auth object | ||
38 | * @file_priv: DRM file that performs the operation | ||
136 | * | 39 | * |
137 | * \param inode device inode. | 40 | * This looks up the unique magic of the passed client and returns it. If the |
138 | * \param file_priv DRM file private. | 41 | * client did not have a magic assigned, yet, a new one is registered. The magic |
139 | * \param cmd command. | 42 | * is stored in the passed drm_auth object. |
140 | * \param arg pointer to a resulting drm_auth structure. | ||
141 | * \return zero on success, or a negative number on failure. | ||
142 | * | 43 | * |
143 | * If there is a magic number in drm_file::magic then use it, otherwise | 44 | * Returns: 0 on success, negative error code on failure. |
144 | * searches an unique non-zero magic number and add it associating it with \p | ||
145 | * file_priv. | ||
146 | * This ioctl needs protection by the drm_global_mutex, which protects | ||
147 | * struct drm_file::magic and struct drm_magic_entry::priv. | ||
148 | */ | 45 | */ |
149 | int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv) | 46 | int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv) |
150 | { | 47 | { |
151 | static drm_magic_t sequence = 0; | ||
152 | static DEFINE_SPINLOCK(lock); | ||
153 | struct drm_auth *auth = data; | 48 | struct drm_auth *auth = data; |
49 | int ret = 0; | ||
154 | 50 | ||
155 | /* Find unique magic */ | 51 | mutex_lock(&dev->struct_mutex); |
156 | if (file_priv->magic) { | 52 | if (!file_priv->magic) { |
157 | auth->magic = file_priv->magic; | 53 | ret = idr_alloc(&file_priv->master->magic_map, file_priv, |
158 | } else { | 54 | 1, 0, GFP_KERNEL); |
159 | do { | 55 | if (ret >= 0) |
160 | spin_lock(&lock); | 56 | file_priv->magic = ret; |
161 | if (!sequence) | ||
162 | ++sequence; /* reserve 0 */ | ||
163 | auth->magic = sequence++; | ||
164 | spin_unlock(&lock); | ||
165 | } while (drm_find_file(file_priv->master, auth->magic)); | ||
166 | file_priv->magic = auth->magic; | ||
167 | drm_add_magic(file_priv->master, file_priv, auth->magic); | ||
168 | } | 57 | } |
58 | auth->magic = file_priv->magic; | ||
59 | mutex_unlock(&dev->struct_mutex); | ||
169 | 60 | ||
170 | DRM_DEBUG("%u\n", auth->magic); | 61 | DRM_DEBUG("%u\n", auth->magic); |
171 | 62 | ||
172 | return 0; | 63 | return ret < 0 ? ret : 0; |
173 | } | 64 | } |
174 | 65 | ||
175 | /** | 66 | /** |
176 | * Authenticate with a magic. | 67 | * drm_authmagic - Authenticate client with a magic |
68 | * @dev: DRM device to operate on | ||
69 | * @data: ioctl data containing the drm_auth object | ||
70 | * @file_priv: DRM file that performs the operation | ||
177 | * | 71 | * |
178 | * \param inode device inode. | 72 | * This looks up a DRM client by the passed magic and authenticates it. |
179 | * \param file_priv DRM file private. | ||
180 | * \param cmd command. | ||
181 | * \param arg pointer to a drm_auth structure. | ||
182 | * \return zero if authentication successed, or a negative number otherwise. | ||
183 | * | 73 | * |
184 | * Checks if \p file_priv is associated with the magic number passed in \arg. | 74 | * Returns: 0 on success, negative error code on failure. |
185 | * This ioctl needs protection by the drm_global_mutex, which protects | ||
186 | * struct drm_file::magic and struct drm_magic_entry::priv. | ||
187 | */ | 75 | */ |
188 | int drm_authmagic(struct drm_device *dev, void *data, | 76 | int drm_authmagic(struct drm_device *dev, void *data, |
189 | struct drm_file *file_priv) | 77 | struct drm_file *file_priv) |
@@ -192,10 +80,14 @@ int drm_authmagic(struct drm_device *dev, void *data, | |||
192 | struct drm_file *file; | 80 | struct drm_file *file; |
193 | 81 | ||
194 | DRM_DEBUG("%u\n", auth->magic); | 82 | DRM_DEBUG("%u\n", auth->magic); |
195 | if ((file = drm_find_file(file_priv->master, auth->magic))) { | 83 | |
84 | mutex_lock(&dev->struct_mutex); | ||
85 | file = idr_find(&file_priv->master->magic_map, auth->magic); | ||
86 | if (file) { | ||
196 | file->authenticated = 1; | 87 | file->authenticated = 1; |
197 | drm_remove_magic(file_priv->master, auth->magic); | 88 | idr_replace(&file_priv->master->magic_map, NULL, auth->magic); |
198 | return 0; | ||
199 | } | 89 | } |
200 | return -EINVAL; | 90 | mutex_unlock(&dev->struct_mutex); |
91 | |||
92 | return file ? 0 : -EINVAL; | ||
201 | } | 93 | } |