diff options
author | Dave Airlie <airlied@linux.ie> | 2007-07-16 20:55:47 -0400 |
---|---|---|
committer | Dave Airlie <airlied@linux.ie> | 2007-07-16 21:04:33 -0400 |
commit | d4e2cbe9cb9219fc924191a6baa2369140cb5ea8 (patch) | |
tree | f4858a3794f47ea3ae36333ae7ca182a46913b65 /drivers/char/drm/drm_drawable.c | |
parent | 62968144e673016180f530fdfe170874b80ab5a7 (diff) |
drm: convert drawable code to using idr
This converts the code for allocating drawables to the Linux idr,
Fixes from: Michel Dänzer <michel@tungstengraphics.com>, Kristian Høgsberg <krh@redhat.com>
Signed-off-by: Dave Airlie <airlied@linux.ie>
Diffstat (limited to 'drivers/char/drm/drm_drawable.c')
-rw-r--r-- | drivers/char/drm/drm_drawable.c | 248 |
1 files changed, 55 insertions, 193 deletions
diff --git a/drivers/char/drm/drm_drawable.c b/drivers/char/drm/drm_drawable.c index 309e585a5442..d6cdba5644e2 100644 --- a/drivers/char/drm/drm_drawable.c +++ b/drivers/char/drm/drm_drawable.c | |||
@@ -44,82 +44,29 @@ int drm_adddraw(DRM_IOCTL_ARGS) | |||
44 | { | 44 | { |
45 | DRM_DEVICE; | 45 | DRM_DEVICE; |
46 | unsigned long irqflags; | 46 | unsigned long irqflags; |
47 | int i, j; | ||
48 | u32 *bitfield = dev->drw_bitfield; | ||
49 | unsigned int bitfield_length = dev->drw_bitfield_length; | ||
50 | struct drm_drawable_info **info = dev->drw_info; | ||
51 | unsigned int info_length = dev->drw_info_length; | ||
52 | struct drm_draw draw; | 47 | struct drm_draw draw; |
48 | int new_id = 0; | ||
49 | int ret; | ||
53 | 50 | ||
54 | for (i = 0, j = 0; i < bitfield_length; i++) { | 51 | again: |
55 | if (bitfield[i] == ~0) | 52 | if (idr_pre_get(&dev->drw_idr, GFP_KERNEL) == 0) { |
56 | continue; | 53 | DRM_ERROR("Out of memory expanding drawable idr\n"); |
57 | 54 | return -ENOMEM; | |
58 | for (; j < 8 * sizeof(*bitfield); j++) | ||
59 | if (!(bitfield[i] & (1 << j))) | ||
60 | goto done; | ||
61 | } | ||
62 | done: | ||
63 | |||
64 | if (i == bitfield_length) { | ||
65 | bitfield_length++; | ||
66 | |||
67 | bitfield = drm_alloc(bitfield_length * sizeof(*bitfield), | ||
68 | DRM_MEM_BUFS); | ||
69 | |||
70 | if (!bitfield) { | ||
71 | DRM_ERROR("Failed to allocate new drawable bitfield\n"); | ||
72 | return DRM_ERR(ENOMEM); | ||
73 | } | ||
74 | |||
75 | if (8 * sizeof(*bitfield) * bitfield_length > info_length) { | ||
76 | info_length += 8 * sizeof(*bitfield); | ||
77 | |||
78 | info = drm_alloc(info_length * sizeof(*info), | ||
79 | DRM_MEM_BUFS); | ||
80 | |||
81 | if (!info) { | ||
82 | DRM_ERROR("Failed to allocate new drawable info" | ||
83 | " array\n"); | ||
84 | |||
85 | drm_free(bitfield, | ||
86 | bitfield_length * sizeof(*bitfield), | ||
87 | DRM_MEM_BUFS); | ||
88 | return DRM_ERR(ENOMEM); | ||
89 | } | ||
90 | } | ||
91 | |||
92 | bitfield[i] = 0; | ||
93 | } | 55 | } |
94 | 56 | ||
95 | draw.handle = i * 8 * sizeof(*bitfield) + j + 1; | ||
96 | DRM_DEBUG("%d\n", draw.handle); | ||
97 | |||
98 | spin_lock_irqsave(&dev->drw_lock, irqflags); | 57 | spin_lock_irqsave(&dev->drw_lock, irqflags); |
99 | 58 | ret = idr_get_new_above(&dev->drw_idr, NULL, 1, &new_id); | |
100 | bitfield[i] |= 1 << j; | 59 | if (ret == -EAGAIN) { |
101 | info[draw.handle - 1] = NULL; | 60 | spin_unlock_irqrestore(&dev->drw_lock, irqflags); |
102 | 61 | goto again; | |
103 | if (bitfield != dev->drw_bitfield) { | ||
104 | memcpy(bitfield, dev->drw_bitfield, dev->drw_bitfield_length * | ||
105 | sizeof(*bitfield)); | ||
106 | drm_free(dev->drw_bitfield, sizeof(*bitfield) * | ||
107 | dev->drw_bitfield_length, DRM_MEM_BUFS); | ||
108 | dev->drw_bitfield = bitfield; | ||
109 | dev->drw_bitfield_length = bitfield_length; | ||
110 | } | ||
111 | |||
112 | if (info != dev->drw_info) { | ||
113 | memcpy(info, dev->drw_info, dev->drw_info_length * | ||
114 | sizeof(*info)); | ||
115 | drm_free(dev->drw_info, sizeof(*info) * dev->drw_info_length, | ||
116 | DRM_MEM_BUFS); | ||
117 | dev->drw_info = info; | ||
118 | dev->drw_info_length = info_length; | ||
119 | } | 62 | } |
120 | 63 | ||
121 | spin_unlock_irqrestore(&dev->drw_lock, irqflags); | 64 | spin_unlock_irqrestore(&dev->drw_lock, irqflags); |
122 | 65 | ||
66 | draw.handle = new_id; | ||
67 | |||
68 | DRM_DEBUG("%d\n", draw.handle); | ||
69 | |||
123 | DRM_COPY_TO_USER_IOCTL((struct drm_draw __user *)data, draw, sizeof(draw)); | 70 | DRM_COPY_TO_USER_IOCTL((struct drm_draw __user *)data, draw, sizeof(draw)); |
124 | 71 | ||
125 | return 0; | 72 | return 0; |
@@ -132,133 +79,44 @@ int drm_rmdraw(DRM_IOCTL_ARGS) | |||
132 | { | 79 | { |
133 | DRM_DEVICE; | 80 | DRM_DEVICE; |
134 | struct drm_draw draw; | 81 | struct drm_draw draw; |
135 | int id, idx; | ||
136 | unsigned int shift; | ||
137 | unsigned long irqflags; | 82 | unsigned long irqflags; |
138 | u32 *bitfield = dev->drw_bitfield; | ||
139 | unsigned int bitfield_length = dev->drw_bitfield_length; | ||
140 | struct drm_drawable_info **info = dev->drw_info; | ||
141 | unsigned int info_length = dev->drw_info_length; | ||
142 | 83 | ||
143 | DRM_COPY_FROM_USER_IOCTL(draw, (struct drm_draw __user *) data, | 84 | DRM_COPY_FROM_USER_IOCTL(draw, (struct drm_draw __user *) data, |
144 | sizeof(draw)); | 85 | sizeof(draw)); |
145 | 86 | ||
146 | id = draw.handle - 1; | ||
147 | idx = id / (8 * sizeof(*bitfield)); | ||
148 | shift = id % (8 * sizeof(*bitfield)); | ||
149 | |||
150 | if (idx < 0 || idx >= bitfield_length || | ||
151 | !(bitfield[idx] & (1 << shift))) { | ||
152 | DRM_DEBUG("No such drawable %d\n", draw.handle); | ||
153 | return 0; | ||
154 | } | ||
155 | |||
156 | spin_lock_irqsave(&dev->drw_lock, irqflags); | 87 | spin_lock_irqsave(&dev->drw_lock, irqflags); |
157 | 88 | ||
158 | bitfield[idx] &= ~(1 << shift); | 89 | drm_free(drm_get_drawable_info(dev, draw.handle), |
159 | 90 | sizeof(struct drm_drawable_info), DRM_MEM_BUFS); | |
160 | spin_unlock_irqrestore(&dev->drw_lock, irqflags); | ||
161 | |||
162 | if (info[id]) { | ||
163 | drm_free(info[id]->rects, info[id]->num_rects * | ||
164 | sizeof(struct drm_clip_rect), DRM_MEM_BUFS); | ||
165 | drm_free(info[id], sizeof(**info), DRM_MEM_BUFS); | ||
166 | } | ||
167 | |||
168 | /* Can we shrink the arrays? */ | ||
169 | if (idx == bitfield_length - 1) { | ||
170 | while (idx >= 0 && !bitfield[idx]) | ||
171 | --idx; | ||
172 | |||
173 | bitfield_length = idx + 1; | ||
174 | |||
175 | bitfield = NULL; | ||
176 | |||
177 | if (bitfield_length) { | ||
178 | if (bitfield_length != dev->drw_bitfield_length) | ||
179 | bitfield = drm_alloc(bitfield_length * | ||
180 | sizeof(*bitfield), | ||
181 | DRM_MEM_BUFS); | ||
182 | |||
183 | if (!bitfield) { | ||
184 | bitfield = dev->drw_bitfield; | ||
185 | bitfield_length = dev->drw_bitfield_length; | ||
186 | } | ||
187 | } | ||
188 | } | ||
189 | |||
190 | if (bitfield != dev->drw_bitfield) { | ||
191 | info_length = 8 * sizeof(*bitfield) * bitfield_length; | ||
192 | |||
193 | if (info_length) { | ||
194 | info = drm_alloc(info_length * sizeof(*info), | ||
195 | DRM_MEM_BUFS); | ||
196 | |||
197 | if (!info) { | ||
198 | info = dev->drw_info; | ||
199 | info_length = dev->drw_info_length; | ||
200 | } | ||
201 | } else | ||
202 | info = NULL; | ||
203 | |||
204 | spin_lock_irqsave(&dev->drw_lock, irqflags); | ||
205 | |||
206 | if (bitfield) | ||
207 | memcpy(bitfield, dev->drw_bitfield, bitfield_length * | ||
208 | sizeof(*bitfield)); | ||
209 | drm_free(dev->drw_bitfield, sizeof(*bitfield) * | ||
210 | dev->drw_bitfield_length, DRM_MEM_BUFS); | ||
211 | dev->drw_bitfield = bitfield; | ||
212 | dev->drw_bitfield_length = bitfield_length; | ||
213 | |||
214 | if (info != dev->drw_info) { | ||
215 | if (info) | ||
216 | memcpy(info, dev->drw_info, info_length * | ||
217 | sizeof(*info)); | ||
218 | drm_free(dev->drw_info, sizeof(*info) * | ||
219 | dev->drw_info_length, DRM_MEM_BUFS); | ||
220 | dev->drw_info = info; | ||
221 | dev->drw_info_length = info_length; | ||
222 | } | ||
223 | 91 | ||
224 | spin_unlock_irqrestore(&dev->drw_lock, irqflags); | 92 | idr_remove(&dev->drw_idr, draw.handle); |
225 | } | ||
226 | 93 | ||
94 | spin_unlock_irqrestore(&dev->drw_lock, irqflags); | ||
227 | DRM_DEBUG("%d\n", draw.handle); | 95 | DRM_DEBUG("%d\n", draw.handle); |
228 | return 0; | 96 | return 0; |
229 | } | 97 | } |
230 | 98 | ||
231 | int drm_update_drawable_info(DRM_IOCTL_ARGS) { | 99 | int drm_update_drawable_info(DRM_IOCTL_ARGS) |
100 | { | ||
232 | DRM_DEVICE; | 101 | DRM_DEVICE; |
233 | struct drm_update_draw update; | 102 | struct drm_update_draw update; |
234 | unsigned int id, idx, shift; | 103 | unsigned long irqflags; |
235 | u32 *bitfield = dev->drw_bitfield; | ||
236 | unsigned long irqflags, bitfield_length = dev->drw_bitfield_length; | ||
237 | struct drm_drawable_info *info; | ||
238 | struct drm_clip_rect *rects; | 104 | struct drm_clip_rect *rects; |
105 | struct drm_drawable_info *info; | ||
239 | int err; | 106 | int err; |
240 | 107 | ||
241 | DRM_COPY_FROM_USER_IOCTL(update, (struct drm_update_draw __user *) data, | 108 | DRM_COPY_FROM_USER_IOCTL(update, (struct drm_update_draw __user *) data, |
242 | sizeof(update)); | 109 | sizeof(update)); |
243 | 110 | ||
244 | id = update.handle - 1; | 111 | info = idr_find(&dev->drw_idr, update.handle); |
245 | idx = id / (8 * sizeof(*bitfield)); | ||
246 | shift = id % (8 * sizeof(*bitfield)); | ||
247 | |||
248 | if (idx < 0 || idx >= bitfield_length || | ||
249 | !(bitfield[idx] & (1 << shift))) { | ||
250 | DRM_ERROR("No such drawable %d\n", update.handle); | ||
251 | return DRM_ERR(EINVAL); | ||
252 | } | ||
253 | |||
254 | info = dev->drw_info[id]; | ||
255 | |||
256 | if (!info) { | 112 | if (!info) { |
257 | info = drm_calloc(1, sizeof(struct drm_drawable_info), DRM_MEM_BUFS); | 113 | info = drm_calloc(1, sizeof(*info), DRM_MEM_BUFS); |
258 | 114 | if (!info) | |
259 | if (!info) { | 115 | return -ENOMEM; |
260 | DRM_ERROR("Failed to allocate drawable info memory\n"); | 116 | if (IS_ERR(idr_replace(&dev->drw_idr, info, update.handle))) { |
261 | return DRM_ERR(ENOMEM); | 117 | DRM_ERROR("No such drawable %d\n", update.handle); |
118 | drm_free(info, sizeof(*info), DRM_MEM_BUFS); | ||
119 | return -EINVAL; | ||
262 | } | 120 | } |
263 | } | 121 | } |
264 | 122 | ||
@@ -295,12 +153,11 @@ int drm_update_drawable_info(DRM_IOCTL_ARGS) { | |||
295 | 153 | ||
296 | info->rects = rects; | 154 | info->rects = rects; |
297 | info->num_rects = update.num; | 155 | info->num_rects = update.num; |
298 | dev->drw_info[id] = info; | ||
299 | 156 | ||
300 | spin_unlock_irqrestore(&dev->drw_lock, irqflags); | 157 | spin_unlock_irqrestore(&dev->drw_lock, irqflags); |
301 | 158 | ||
302 | DRM_DEBUG("Updated %d cliprects for drawable %d\n", | 159 | DRM_DEBUG("Updated %d cliprects for drawable %d\n", |
303 | info->num_rects, id); | 160 | info->num_rects, update.handle); |
304 | break; | 161 | break; |
305 | default: | 162 | default: |
306 | DRM_ERROR("Invalid update type %d\n", update.type); | 163 | DRM_ERROR("Invalid update type %d\n", update.type); |
@@ -310,11 +167,9 @@ int drm_update_drawable_info(DRM_IOCTL_ARGS) { | |||
310 | return 0; | 167 | return 0; |
311 | 168 | ||
312 | error: | 169 | error: |
313 | if (!dev->drw_info[id]) | 170 | if (rects != info->rects) |
314 | drm_free(info, sizeof(*info), DRM_MEM_BUFS); | 171 | drm_free(rects, update.num * sizeof(struct drm_clip_rect), |
315 | else if (rects != dev->drw_info[id]->rects) | 172 | DRM_MEM_BUFS); |
316 | drm_free(rects, update.num * | ||
317 | sizeof(struct drm_clip_rect), DRM_MEM_BUFS); | ||
318 | 173 | ||
319 | return err; | 174 | return err; |
320 | } | 175 | } |
@@ -322,20 +177,27 @@ error: | |||
322 | /** | 177 | /** |
323 | * Caller must hold the drawable spinlock! | 178 | * Caller must hold the drawable spinlock! |
324 | */ | 179 | */ |
325 | struct drm_drawable_info *drm_get_drawable_info(struct drm_device *dev, drm_drawable_t id) { | 180 | struct drm_drawable_info *drm_get_drawable_info(struct drm_device *dev, drm_drawable_t id) |
326 | u32 *bitfield = dev->drw_bitfield; | 181 | { |
327 | unsigned int idx, shift; | 182 | return idr_find(&dev->drw_idr, id); |
328 | 183 | } | |
329 | id--; | 184 | EXPORT_SYMBOL(drm_get_drawable_info); |
330 | idx = id / (8 * sizeof(*bitfield)); | 185 | |
331 | shift = id % (8 * sizeof(*bitfield)); | 186 | static int drm_drawable_free(int idr, void *p, void *data) |
332 | 187 | { | |
333 | if (idx < 0 || idx >= dev->drw_bitfield_length || | 188 | struct drm_drawable_info *info = p; |
334 | !(bitfield[idx] & (1 << shift))) { | 189 | |
335 | DRM_DEBUG("No such drawable %d\n", id); | 190 | if (info) { |
336 | return NULL; | 191 | drm_free(info->rects, info->num_rects * |
192 | sizeof(struct drm_clip_rect), DRM_MEM_BUFS); | ||
193 | drm_free(info, sizeof(*info), DRM_MEM_BUFS); | ||
337 | } | 194 | } |
338 | 195 | ||
339 | return dev->drw_info[id]; | 196 | return 0; |
197 | } | ||
198 | |||
199 | void drm_drawable_free_all(struct drm_device *dev) | ||
200 | { | ||
201 | idr_for_each(&dev->drw_idr, drm_drawable_free, NULL); | ||
202 | idr_remove_all(&dev->drw_idr); | ||
340 | } | 203 | } |
341 | EXPORT_SYMBOL(drm_get_drawable_info); | ||