diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-16 21:24:37 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-16 21:24:37 -0400 |
commit | a5fcaa210626a79465321e344c91a6a7dc3881fa (patch) | |
tree | 8b42dc877829cead9a38fbda664b4c9d3c071fc4 | |
parent | 489de30259e667d7bc47da9da44a0270b050cd97 (diff) | |
parent | d4e2cbe9cb9219fc924191a6baa2369140cb5ea8 (diff) |
Merge branch 'drm-patches' of ssh://master.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6
* 'drm-patches' of ssh://master.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6:
drm: convert drawable code to using idr
drm: convert drm context code to use Linux idr
-rw-r--r-- | drivers/char/drm/drmP.h | 11 | ||||
-rw-r--r-- | drivers/char/drm/drm_context.c | 131 | ||||
-rw-r--r-- | drivers/char/drm/drm_drawable.c | 248 | ||||
-rw-r--r-- | drivers/char/drm/drm_drv.c | 15 |
4 files changed, 93 insertions, 312 deletions
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index 1277693e9ca4..0df87fc3dcb2 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 */ |
@@ -750,10 +751,7 @@ struct drm_device { | |||
750 | /** \name Drawable information */ | 751 | /** \name Drawable information */ |
751 | /*@{ */ | 752 | /*@{ */ |
752 | spinlock_t drw_lock; | 753 | spinlock_t drw_lock; |
753 | unsigned int drw_bitfield_length; | 754 | struct idr drw_idr; |
754 | u32 *drw_bitfield; | ||
755 | unsigned int drw_info_length; | ||
756 | struct drm_drawable_info **drw_info; | ||
757 | /*@} */ | 755 | /*@} */ |
758 | }; | 756 | }; |
759 | 757 | ||
@@ -903,6 +901,7 @@ extern int drm_update_drawable_info(struct inode *inode, struct file *filp, | |||
903 | unsigned int cmd, unsigned long arg); | 901 | unsigned int cmd, unsigned long arg); |
904 | extern struct drm_drawable_info *drm_get_drawable_info(struct drm_device *dev, | 902 | extern struct drm_drawable_info *drm_get_drawable_info(struct drm_device *dev, |
905 | drm_drawable_t id); | 903 | drm_drawable_t id); |
904 | extern void drm_drawable_free_all(struct drm_device *dev); | ||
906 | 905 | ||
907 | /* Authentication IOCTL support (drm_auth.h) */ | 906 | /* Authentication IOCTL support (drm_auth.h) */ |
908 | extern int drm_getmagic(struct inode *inode, struct file *filp, | 907 | extern int drm_getmagic(struct inode *inode, struct file *filp, |
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 | } |
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); | ||
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 */ |