diff options
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/drm/drmP.h | 5 | ||||
-rw-r--r-- | drivers/char/drm/drm_context.c | 131 |
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 | */ |
59 | void drm_ctxbitmap_free(struct drm_device * dev, int ctx_handle) | 59 | void 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 | */ |
88 | static int drm_ctxbitmap_next(struct drm_device * dev) | 75 | static 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 | ||
80 | again: | ||
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 | */ |
150 | int drm_ctxbitmap_init(struct drm_device * dev) | 103 | int 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 | */ |
183 | void drm_ctxbitmap_cleanup(struct drm_device * dev) | 117 | void 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 | */ |
212 | int drm_getsareactx(struct inode *inode, struct file *filp, | 142 | int 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 | */ |
263 | int drm_setsareactx(struct inode *inode, struct file *filp, | 193 | int 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 | } |