aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDave Airlie <airlied@linux.ie>2007-07-16 20:55:47 -0400
committerDave Airlie <airlied@linux.ie>2007-07-16 21:04:33 -0400
commitd4e2cbe9cb9219fc924191a6baa2369140cb5ea8 (patch)
treef4858a3794f47ea3ae36333ae7ca182a46913b65 /drivers
parent62968144e673016180f530fdfe170874b80ab5a7 (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')
-rw-r--r--drivers/char/drm/drmP.h6
-rw-r--r--drivers/char/drm/drm_drawable.c248
-rw-r--r--drivers/char/drm/drm_drv.c15
3 files changed, 60 insertions, 209 deletions
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
index b1cafe36611e..0df87fc3dcb2 100644
--- a/drivers/char/drm/drmP.h
+++ b/drivers/char/drm/drmP.h
@@ -751,10 +751,7 @@ struct drm_device {
751 /** \name Drawable information */ 751 /** \name Drawable information */
752 /*@{ */ 752 /*@{ */
753 spinlock_t drw_lock; 753 spinlock_t drw_lock;
754 unsigned int drw_bitfield_length; 754 struct idr drw_idr;
755 u32 *drw_bitfield;
756 unsigned int drw_info_length;
757 struct drm_drawable_info **drw_info;
758 /*@} */ 755 /*@} */
759}; 756};
760 757
@@ -904,6 +901,7 @@ extern int drm_update_drawable_info(struct inode *inode, struct file *filp,
904 unsigned int cmd, unsigned long arg); 901 unsigned int cmd, unsigned long arg);
905extern struct drm_drawable_info *drm_get_drawable_info(struct drm_device *dev, 902extern struct drm_drawable_info *drm_get_drawable_info(struct drm_device *dev,
906 drm_drawable_t id); 903 drm_drawable_t id);
904extern void drm_drawable_free_all(struct drm_device *dev);
907 905
908 /* Authentication IOCTL support (drm_auth.h) */ 906 /* Authentication IOCTL support (drm_auth.h) */
909extern int drm_getmagic(struct inode *inode, struct file *filp, 907extern int drm_getmagic(struct inode *inode, struct file *filp,
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++) { 51again:
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 }
62done:
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
231int drm_update_drawable_info(DRM_IOCTL_ARGS) { 99int 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
312error: 169error:
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 */
325struct drm_drawable_info *drm_get_drawable_info(struct drm_device *dev, drm_drawable_t id) { 180struct 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--; 184EXPORT_SYMBOL(drm_get_drawable_info);
330 idx = id / (8 * sizeof(*bitfield)); 185
331 shift = id % (8 * sizeof(*bitfield)); 186static 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
199void 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}
341EXPORT_SYMBOL(drm_get_drawable_info);
diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c
index d5cf5cfccf78..19994cd865de 100644
--- a/drivers/char/drm/drm_drv.c
+++ b/drivers/char/drm/drm_drv.c
@@ -151,19 +151,10 @@ int drm_lastclose(struct drm_device * dev)
151 if (dev->irq_enabled) 151 if (dev->irq_enabled)
152 drm_irq_uninstall(dev); 152 drm_irq_uninstall(dev);
153 153
154 /* Free drawable information memory */
155 for (i = 0; i < dev->drw_bitfield_length / sizeof(*dev->drw_bitfield);
156 i++) {
157 struct drm_drawable_info *info = drm_get_drawable_info(dev, i);
158
159 if (info) {
160 drm_free(info->rects, info->num_rects *
161 sizeof(struct drm_clip_rect), DRM_MEM_BUFS);
162 drm_free(info, sizeof(*info), DRM_MEM_BUFS);
163 }
164 }
165
166 mutex_lock(&dev->struct_mutex); 154 mutex_lock(&dev->struct_mutex);
155
156 /* Free drawable information memory */
157 drm_drawable_free_all(dev);
167 del_timer(&dev->timer); 158 del_timer(&dev->timer);
168 159
169 /* Clear pid list */ 160 /* Clear pid list */