aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/drm/drmP.h5
-rw-r--r--drivers/char/drm/drm_context.c131
2 files changed, 33 insertions, 103 deletions
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
index 1277693e9ca4..b1cafe36611e 100644
--- a/drivers/char/drm/drmP.h
+++ b/drivers/char/drm/drmP.h
@@ -75,6 +75,8 @@
75#include <asm/pgalloc.h> 75#include <asm/pgalloc.h>
76#include "drm.h" 76#include "drm.h"
77 77
78#include <linux/idr.h>
79
78#define __OS_HAS_AGP (defined(CONFIG_AGP) || (defined(CONFIG_AGP_MODULE) && defined(MODULE))) 80#define __OS_HAS_AGP (defined(CONFIG_AGP) || (defined(CONFIG_AGP_MODULE) && defined(MODULE)))
79#define __OS_HAS_MTRR (defined(CONFIG_MTRR)) 81#define __OS_HAS_MTRR (defined(CONFIG_MTRR))
80 82
@@ -676,8 +678,7 @@ struct drm_device {
676 int ctx_count; /**< Number of context handles */ 678 int ctx_count; /**< Number of context handles */
677 struct mutex ctxlist_mutex; /**< For ctxlist */ 679 struct mutex ctxlist_mutex; /**< For ctxlist */
678 680
679 struct drm_map **context_sareas; /**< per-context SAREA's */ 681 struct idr ctx_idr;
680 int max_context;
681 682
682 struct list_head vmalist; /**< List of vmas (for debugging) */ 683 struct list_head vmalist; /**< List of vmas (for debugging) */
683 struct drm_lock_data lock; /**< Information on hardware lock */ 684 struct drm_lock_data lock; /**< Information on hardware lock */
diff --git a/drivers/char/drm/drm_context.c b/drivers/char/drm/drm_context.c
index 7fc055adec25..61ad986baa8d 100644
--- a/drivers/char/drm/drm_context.c
+++ b/drivers/char/drm/drm_context.c
@@ -53,26 +53,14 @@
53 * \param ctx_handle context handle. 53 * \param ctx_handle context handle.
54 * 54 *
55 * Clears the bit specified by \p ctx_handle in drm_device::ctx_bitmap and the entry 55 * Clears the bit specified by \p ctx_handle in drm_device::ctx_bitmap and the entry
56 * in drm_device::context_sareas, while holding the drm_device::struct_mutex 56 * in drm_device::ctx_idr, while holding the drm_device::struct_mutex
57 * lock. 57 * lock.
58 */ 58 */
59void drm_ctxbitmap_free(struct drm_device * dev, int ctx_handle) 59void drm_ctxbitmap_free(struct drm_device * dev, int ctx_handle)
60{ 60{
61 if (ctx_handle < 0) 61 mutex_lock(&dev->struct_mutex);
62 goto failed; 62 idr_remove(&dev->ctx_idr, ctx_handle);
63 if (!dev->ctx_bitmap) 63 mutex_unlock(&dev->struct_mutex);
64 goto failed;
65
66 if (ctx_handle < DRM_MAX_CTXBITMAP) {
67 mutex_lock(&dev->struct_mutex);
68 clear_bit(ctx_handle, dev->ctx_bitmap);
69 dev->context_sareas[ctx_handle] = NULL;
70 mutex_unlock(&dev->struct_mutex);
71 return;
72 }
73 failed:
74 DRM_ERROR("Attempt to free invalid context handle: %d\n", ctx_handle);
75 return;
76} 64}
77 65
78/** 66/**
@@ -81,62 +69,28 @@ void drm_ctxbitmap_free(struct drm_device * dev, int ctx_handle)
81 * \param dev DRM device. 69 * \param dev DRM device.
82 * \return (non-negative) context handle on success or a negative number on failure. 70 * \return (non-negative) context handle on success or a negative number on failure.
83 * 71 *
84 * Find the first zero bit in drm_device::ctx_bitmap and (re)allocates 72 * Allocate a new idr from drm_device::ctx_idr while holding the
85 * drm_device::context_sareas to accommodate the new entry while holding the
86 * drm_device::struct_mutex lock. 73 * drm_device::struct_mutex lock.
87 */ 74 */
88static int drm_ctxbitmap_next(struct drm_device * dev) 75static int drm_ctxbitmap_next(struct drm_device * dev)
89{ 76{
90 int bit; 77 int new_id;
91 78 int ret;
92 if (!dev->ctx_bitmap)
93 return -1;
94 79
80again:
81 if (idr_pre_get(&dev->ctx_idr, GFP_KERNEL) == 0) {
82 DRM_ERROR("Out of memory expanding drawable idr\n");
83 return -ENOMEM;
84 }
95 mutex_lock(&dev->struct_mutex); 85 mutex_lock(&dev->struct_mutex);
96 bit = find_first_zero_bit(dev->ctx_bitmap, DRM_MAX_CTXBITMAP); 86 ret = idr_get_new_above(&dev->ctx_idr, NULL,
97 if (bit < DRM_MAX_CTXBITMAP) { 87 DRM_RESERVED_CONTEXTS, &new_id);
98 set_bit(bit, dev->ctx_bitmap); 88 if (ret == -EAGAIN) {
99 DRM_DEBUG("drm_ctxbitmap_next bit : %d\n", bit);
100 if ((bit + 1) > dev->max_context) {
101 dev->max_context = (bit + 1);
102 if (dev->context_sareas) {
103 struct drm_map **ctx_sareas;
104
105 ctx_sareas = drm_realloc(dev->context_sareas,
106 (dev->max_context -
107 1) *
108 sizeof(*dev->
109 context_sareas),
110 dev->max_context *
111 sizeof(*dev->
112 context_sareas),
113 DRM_MEM_MAPS);
114 if (!ctx_sareas) {
115 clear_bit(bit, dev->ctx_bitmap);
116 mutex_unlock(&dev->struct_mutex);
117 return -1;
118 }
119 dev->context_sareas = ctx_sareas;
120 dev->context_sareas[bit] = NULL;
121 } else {
122 /* max_context == 1 at this point */
123 dev->context_sareas =
124 drm_alloc(dev->max_context *
125 sizeof(*dev->context_sareas),
126 DRM_MEM_MAPS);
127 if (!dev->context_sareas) {
128 clear_bit(bit, dev->ctx_bitmap);
129 mutex_unlock(&dev->struct_mutex);
130 return -1;
131 }
132 dev->context_sareas[bit] = NULL;
133 }
134 }
135 mutex_unlock(&dev->struct_mutex); 89 mutex_unlock(&dev->struct_mutex);
136 return bit; 90 goto again;
137 } 91 }
138 mutex_unlock(&dev->struct_mutex); 92 mutex_unlock(&dev->struct_mutex);
139 return -1; 93 return new_id;
140} 94}
141 95
142/** 96/**
@@ -144,31 +98,11 @@ static int drm_ctxbitmap_next(struct drm_device * dev)
144 * 98 *
145 * \param dev DRM device. 99 * \param dev DRM device.
146 * 100 *
147 * Allocates and initialize drm_device::ctx_bitmap and drm_device::context_sareas, while holding 101 * Initialise the drm_device::ctx_idr
148 * the drm_device::struct_mutex lock.
149 */ 102 */
150int drm_ctxbitmap_init(struct drm_device * dev) 103int drm_ctxbitmap_init(struct drm_device * dev)
151{ 104{
152 int i; 105 idr_init(&dev->ctx_idr);
153 int temp;
154
155 mutex_lock(&dev->struct_mutex);
156 dev->ctx_bitmap = (unsigned long *)drm_alloc(PAGE_SIZE,
157 DRM_MEM_CTXBITMAP);
158 if (dev->ctx_bitmap == NULL) {
159 mutex_unlock(&dev->struct_mutex);
160 return -ENOMEM;
161 }
162 memset((void *)dev->ctx_bitmap, 0, PAGE_SIZE);
163 dev->context_sareas = NULL;
164 dev->max_context = -1;
165 mutex_unlock(&dev->struct_mutex);
166
167 for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) {
168 temp = drm_ctxbitmap_next(dev);
169 DRM_DEBUG("drm_ctxbitmap_init : %d\n", temp);
170 }
171
172 return 0; 106 return 0;
173} 107}
174 108
@@ -177,17 +111,13 @@ int drm_ctxbitmap_init(struct drm_device * dev)
177 * 111 *
178 * \param dev DRM device. 112 * \param dev DRM device.
179 * 113 *
180 * Frees drm_device::ctx_bitmap and drm_device::context_sareas, while holding 114 * Free all idr members using drm_ctx_sarea_free helper function
181 * the drm_device::struct_mutex lock. 115 * while holding the drm_device::struct_mutex lock.
182 */ 116 */
183void drm_ctxbitmap_cleanup(struct drm_device * dev) 117void drm_ctxbitmap_cleanup(struct drm_device * dev)
184{ 118{
185 mutex_lock(&dev->struct_mutex); 119 mutex_lock(&dev->struct_mutex);
186 if (dev->context_sareas) 120 idr_remove_all(&dev->ctx_idr);
187 drm_free(dev->context_sareas,
188 sizeof(*dev->context_sareas) *
189 dev->max_context, DRM_MEM_MAPS);
190 drm_free((void *)dev->ctx_bitmap, PAGE_SIZE, DRM_MEM_CTXBITMAP);
191 mutex_unlock(&dev->struct_mutex); 121 mutex_unlock(&dev->struct_mutex);
192} 122}
193 123
@@ -206,7 +136,7 @@ void drm_ctxbitmap_cleanup(struct drm_device * dev)
206 * \param arg user argument pointing to a drm_ctx_priv_map structure. 136 * \param arg user argument pointing to a drm_ctx_priv_map structure.
207 * \return zero on success or a negative number on failure. 137 * \return zero on success or a negative number on failure.
208 * 138 *
209 * Gets the map from drm_device::context_sareas with the handle specified and 139 * Gets the map from drm_device::ctx_idr with the handle specified and
210 * returns its handle. 140 * returns its handle.
211 */ 141 */
212int drm_getsareactx(struct inode *inode, struct file *filp, 142int drm_getsareactx(struct inode *inode, struct file *filp,
@@ -223,13 +153,13 @@ int drm_getsareactx(struct inode *inode, struct file *filp,
223 return -EFAULT; 153 return -EFAULT;
224 154
225 mutex_lock(&dev->struct_mutex); 155 mutex_lock(&dev->struct_mutex);
226 if (dev->max_context < 0 156
227 || request.ctx_id >= (unsigned)dev->max_context) { 157 map = idr_find(&dev->ctx_idr, request.ctx_id);
158 if (!map) {
228 mutex_unlock(&dev->struct_mutex); 159 mutex_unlock(&dev->struct_mutex);
229 return -EINVAL; 160 return -EINVAL;
230 } 161 }
231 162
232 map = dev->context_sareas[request.ctx_id];
233 mutex_unlock(&dev->struct_mutex); 163 mutex_unlock(&dev->struct_mutex);
234 164
235 request.handle = NULL; 165 request.handle = NULL;
@@ -258,7 +188,7 @@ int drm_getsareactx(struct inode *inode, struct file *filp,
258 * \return zero on success or a negative number on failure. 188 * \return zero on success or a negative number on failure.
259 * 189 *
260 * Searches the mapping specified in \p arg and update the entry in 190 * Searches the mapping specified in \p arg and update the entry in
261 * drm_device::context_sareas with it. 191 * drm_device::ctx_idr with it.
262 */ 192 */
263int drm_setsareactx(struct inode *inode, struct file *filp, 193int drm_setsareactx(struct inode *inode, struct file *filp,
264 unsigned int cmd, unsigned long arg) 194 unsigned int cmd, unsigned long arg)
@@ -288,11 +218,10 @@ int drm_setsareactx(struct inode *inode, struct file *filp,
288 map = r_list->map; 218 map = r_list->map;
289 if (!map) 219 if (!map)
290 goto bad; 220 goto bad;
291 if (dev->max_context < 0) 221
292 goto bad; 222 if (IS_ERR(idr_replace(&dev->ctx_idr, map, request.ctx_id)))
293 if (request.ctx_id >= (unsigned)dev->max_context)
294 goto bad; 223 goto bad;
295 dev->context_sareas[request.ctx_id] = map; 224
296 mutex_unlock(&dev->struct_mutex); 225 mutex_unlock(&dev->struct_mutex);
297 return 0; 226 return 0;
298} 227}