diff options
Diffstat (limited to 'drivers/gpu/drm/drm_drv.c')
-rw-r--r-- | drivers/gpu/drm/drm_drv.c | 107 |
1 files changed, 49 insertions, 58 deletions
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 3ab1e9cc4692..14c7a23dc157 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c | |||
@@ -74,6 +74,9 @@ static struct drm_ioctl_desc drm_ioctls[] = { | |||
74 | DRM_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | 74 | DRM_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
75 | DRM_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_getsareactx, DRM_AUTH), | 75 | DRM_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_getsareactx, DRM_AUTH), |
76 | 76 | ||
77 | DRM_IOCTL_DEF(DRM_IOCTL_SET_MASTER, drm_setmaster_ioctl, DRM_ROOT_ONLY), | ||
78 | DRM_IOCTL_DEF(DRM_IOCTL_DROP_MASTER, drm_dropmaster_ioctl, DRM_ROOT_ONLY), | ||
79 | |||
77 | DRM_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_addctx, DRM_AUTH|DRM_ROOT_ONLY), | 80 | DRM_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_addctx, DRM_AUTH|DRM_ROOT_ONLY), |
78 | DRM_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | 81 | DRM_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
79 | DRM_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | 82 | DRM_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |
@@ -123,6 +126,23 @@ static struct drm_ioctl_desc drm_ioctls[] = { | |||
123 | DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, 0), | 126 | DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, 0), |
124 | DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH), | 127 | DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH), |
125 | DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH), | 128 | DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH), |
129 | |||
130 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_MASTER|DRM_CONTROL_ALLOW), | ||
131 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_MASTER|DRM_CONTROL_ALLOW), | ||
132 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW), | ||
133 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW), | ||
134 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_MASTER), | ||
135 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER), | ||
136 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETENCODER, drm_mode_getencoder, DRM_MASTER|DRM_CONTROL_ALLOW), | ||
137 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, DRM_MASTER|DRM_CONTROL_ALLOW), | ||
138 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_mode_attachmode_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW), | ||
139 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_mode_detachmode_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW), | ||
140 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, DRM_MASTER | DRM_CONTROL_ALLOW), | ||
141 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_mode_connector_property_set_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW), | ||
142 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW), | ||
143 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_MASTER|DRM_CONTROL_ALLOW), | ||
144 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_CONTROL_ALLOW), | ||
145 | DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_CONTROL_ALLOW), | ||
126 | }; | 146 | }; |
127 | 147 | ||
128 | #define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) | 148 | #define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) |
@@ -138,8 +158,6 @@ static struct drm_ioctl_desc drm_ioctls[] = { | |||
138 | */ | 158 | */ |
139 | int drm_lastclose(struct drm_device * dev) | 159 | int drm_lastclose(struct drm_device * dev) |
140 | { | 160 | { |
141 | struct drm_magic_entry *pt, *next; | ||
142 | struct drm_map_list *r_list, *list_t; | ||
143 | struct drm_vma_entry *vma, *vma_temp; | 161 | struct drm_vma_entry *vma, *vma_temp; |
144 | int i; | 162 | int i; |
145 | 163 | ||
@@ -149,13 +167,7 @@ int drm_lastclose(struct drm_device * dev) | |||
149 | dev->driver->lastclose(dev); | 167 | dev->driver->lastclose(dev); |
150 | DRM_DEBUG("driver lastclose completed\n"); | 168 | DRM_DEBUG("driver lastclose completed\n"); |
151 | 169 | ||
152 | if (dev->unique) { | 170 | if (dev->irq_enabled && !drm_core_check_feature(dev, DRIVER_MODESET)) |
153 | drm_free(dev->unique, strlen(dev->unique) + 1, DRM_MEM_DRIVER); | ||
154 | dev->unique = NULL; | ||
155 | dev->unique_len = 0; | ||
156 | } | ||
157 | |||
158 | if (dev->irq_enabled) | ||
159 | drm_irq_uninstall(dev); | 171 | drm_irq_uninstall(dev); |
160 | 172 | ||
161 | mutex_lock(&dev->struct_mutex); | 173 | mutex_lock(&dev->struct_mutex); |
@@ -164,18 +176,9 @@ int drm_lastclose(struct drm_device * dev) | |||
164 | drm_drawable_free_all(dev); | 176 | drm_drawable_free_all(dev); |
165 | del_timer(&dev->timer); | 177 | del_timer(&dev->timer); |
166 | 178 | ||
167 | /* Clear pid list */ | ||
168 | if (dev->magicfree.next) { | ||
169 | list_for_each_entry_safe(pt, next, &dev->magicfree, head) { | ||
170 | list_del(&pt->head); | ||
171 | drm_ht_remove_item(&dev->magiclist, &pt->hash_item); | ||
172 | drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC); | ||
173 | } | ||
174 | drm_ht_remove(&dev->magiclist); | ||
175 | } | ||
176 | |||
177 | /* Clear AGP information */ | 179 | /* Clear AGP information */ |
178 | if (drm_core_has_AGP(dev) && dev->agp) { | 180 | if (drm_core_has_AGP(dev) && dev->agp && |
181 | !drm_core_check_feature(dev, DRIVER_MODESET)) { | ||
179 | struct drm_agp_mem *entry, *tempe; | 182 | struct drm_agp_mem *entry, *tempe; |
180 | 183 | ||
181 | /* Remove AGP resources, but leave dev->agp | 184 | /* Remove AGP resources, but leave dev->agp |
@@ -194,7 +197,8 @@ int drm_lastclose(struct drm_device * dev) | |||
194 | dev->agp->acquired = 0; | 197 | dev->agp->acquired = 0; |
195 | dev->agp->enabled = 0; | 198 | dev->agp->enabled = 0; |
196 | } | 199 | } |
197 | if (drm_core_check_feature(dev, DRIVER_SG) && dev->sg) { | 200 | if (drm_core_check_feature(dev, DRIVER_SG) && dev->sg && |
201 | !drm_core_check_feature(dev, DRIVER_MODESET)) { | ||
198 | drm_sg_cleanup(dev->sg); | 202 | drm_sg_cleanup(dev->sg); |
199 | dev->sg = NULL; | 203 | dev->sg = NULL; |
200 | } | 204 | } |
@@ -205,13 +209,6 @@ int drm_lastclose(struct drm_device * dev) | |||
205 | drm_free(vma, sizeof(*vma), DRM_MEM_VMAS); | 209 | drm_free(vma, sizeof(*vma), DRM_MEM_VMAS); |
206 | } | 210 | } |
207 | 211 | ||
208 | list_for_each_entry_safe(r_list, list_t, &dev->maplist, head) { | ||
209 | if (!(r_list->map->flags & _DRM_DRIVER)) { | ||
210 | drm_rmmap_locked(dev, r_list->map); | ||
211 | r_list = NULL; | ||
212 | } | ||
213 | } | ||
214 | |||
215 | if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && dev->queuelist) { | 212 | if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && dev->queuelist) { |
216 | for (i = 0; i < dev->queue_count; i++) { | 213 | for (i = 0; i < dev->queue_count; i++) { |
217 | if (dev->queuelist[i]) { | 214 | if (dev->queuelist[i]) { |
@@ -228,14 +225,11 @@ int drm_lastclose(struct drm_device * dev) | |||
228 | } | 225 | } |
229 | dev->queue_count = 0; | 226 | dev->queue_count = 0; |
230 | 227 | ||
231 | if (drm_core_check_feature(dev, DRIVER_HAVE_DMA)) | 228 | if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) && |
229 | !drm_core_check_feature(dev, DRIVER_MODESET)) | ||
232 | drm_dma_takedown(dev); | 230 | drm_dma_takedown(dev); |
233 | 231 | ||
234 | if (dev->lock.hw_lock) { | 232 | dev->dev_mapping = NULL; |
235 | dev->sigdata.lock = dev->lock.hw_lock = NULL; /* SHM removed */ | ||
236 | dev->lock.file_priv = NULL; | ||
237 | wake_up_interruptible(&dev->lock.lock_queue); | ||
238 | } | ||
239 | mutex_unlock(&dev->struct_mutex); | 233 | mutex_unlock(&dev->struct_mutex); |
240 | 234 | ||
241 | DRM_DEBUG("lastclose completed\n"); | 235 | DRM_DEBUG("lastclose completed\n"); |
@@ -263,6 +257,8 @@ int drm_init(struct drm_driver *driver) | |||
263 | 257 | ||
264 | DRM_DEBUG("\n"); | 258 | DRM_DEBUG("\n"); |
265 | 259 | ||
260 | INIT_LIST_HEAD(&driver->device_list); | ||
261 | |||
266 | for (i = 0; driver->pci_driver.id_table[i].vendor != 0; i++) { | 262 | for (i = 0; driver->pci_driver.id_table[i].vendor != 0; i++) { |
267 | pid = (struct pci_device_id *)&driver->pci_driver.id_table[i]; | 263 | pid = (struct pci_device_id *)&driver->pci_driver.id_table[i]; |
268 | 264 | ||
@@ -298,6 +294,7 @@ EXPORT_SYMBOL(drm_init); | |||
298 | */ | 294 | */ |
299 | static void drm_cleanup(struct drm_device * dev) | 295 | static void drm_cleanup(struct drm_device * dev) |
300 | { | 296 | { |
297 | struct drm_map_list *r_list, *list_temp; | ||
301 | DRM_DEBUG("\n"); | 298 | DRM_DEBUG("\n"); |
302 | 299 | ||
303 | if (!dev) { | 300 | if (!dev) { |
@@ -305,6 +302,8 @@ static void drm_cleanup(struct drm_device * dev) | |||
305 | return; | 302 | return; |
306 | } | 303 | } |
307 | 304 | ||
305 | drm_vblank_cleanup(dev); | ||
306 | |||
308 | drm_lastclose(dev); | 307 | drm_lastclose(dev); |
309 | 308 | ||
310 | if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) && | 309 | if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) && |
@@ -316,46 +315,38 @@ static void drm_cleanup(struct drm_device * dev) | |||
316 | DRM_DEBUG("mtrr_del=%d\n", retval); | 315 | DRM_DEBUG("mtrr_del=%d\n", retval); |
317 | } | 316 | } |
318 | 317 | ||
318 | if (dev->driver->unload) | ||
319 | dev->driver->unload(dev); | ||
320 | |||
319 | if (drm_core_has_AGP(dev) && dev->agp) { | 321 | if (drm_core_has_AGP(dev) && dev->agp) { |
320 | drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS); | 322 | drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS); |
321 | dev->agp = NULL; | 323 | dev->agp = NULL; |
322 | } | 324 | } |
323 | 325 | ||
324 | if (dev->driver->unload) | ||
325 | dev->driver->unload(dev); | ||
326 | |||
327 | drm_ht_remove(&dev->map_hash); | 326 | drm_ht_remove(&dev->map_hash); |
328 | drm_ctxbitmap_cleanup(dev); | 327 | drm_ctxbitmap_cleanup(dev); |
329 | 328 | ||
330 | drm_put_minor(&dev->primary); | 329 | list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head) |
331 | if (drm_put_dev(dev)) | 330 | drm_rmmap(dev, r_list->map); |
332 | DRM_ERROR("Cannot unload module\n"); | ||
333 | } | ||
334 | |||
335 | static int drm_minors_cleanup(int id, void *ptr, void *data) | ||
336 | { | ||
337 | struct drm_minor *minor = ptr; | ||
338 | struct drm_device *dev; | ||
339 | struct drm_driver *driver = data; | ||
340 | 331 | ||
341 | dev = minor->dev; | 332 | if (drm_core_check_feature(dev, DRIVER_MODESET)) |
342 | if (minor->dev->driver != driver) | 333 | drm_put_minor(&dev->control); |
343 | return 0; | ||
344 | 334 | ||
345 | if (minor->type != DRM_MINOR_LEGACY) | 335 | if (dev->driver->driver_features & DRIVER_GEM) |
346 | return 0; | 336 | drm_gem_destroy(dev); |
347 | 337 | ||
348 | if (dev) | 338 | drm_put_minor(&dev->primary); |
349 | pci_dev_put(dev->pdev); | 339 | if (drm_put_dev(dev)) |
350 | drm_cleanup(dev); | 340 | DRM_ERROR("Cannot unload module\n"); |
351 | return 1; | ||
352 | } | 341 | } |
353 | 342 | ||
354 | void drm_exit(struct drm_driver *driver) | 343 | void drm_exit(struct drm_driver *driver) |
355 | { | 344 | { |
345 | struct drm_device *dev, *tmp; | ||
356 | DRM_DEBUG("\n"); | 346 | DRM_DEBUG("\n"); |
357 | 347 | ||
358 | idr_for_each(&drm_minors_idr, &drm_minors_cleanup, driver); | 348 | list_for_each_entry_safe(dev, tmp, &driver->device_list, driver_item) |
349 | drm_cleanup(dev); | ||
359 | 350 | ||
360 | DRM_INFO("Module unloaded\n"); | 351 | DRM_INFO("Module unloaded\n"); |
361 | } | 352 | } |
@@ -501,7 +492,7 @@ int drm_ioctl(struct inode *inode, struct file *filp, | |||
501 | retcode = -EINVAL; | 492 | retcode = -EINVAL; |
502 | } else if (((ioctl->flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN)) || | 493 | } else if (((ioctl->flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN)) || |
503 | ((ioctl->flags & DRM_AUTH) && !file_priv->authenticated) || | 494 | ((ioctl->flags & DRM_AUTH) && !file_priv->authenticated) || |
504 | ((ioctl->flags & DRM_MASTER) && !file_priv->master)) { | 495 | ((ioctl->flags & DRM_MASTER) && !file_priv->is_master)) { |
505 | retcode = -EACCES; | 496 | retcode = -EACCES; |
506 | } else { | 497 | } else { |
507 | if (cmd & (IOC_IN | IOC_OUT)) { | 498 | if (cmd & (IOC_IN | IOC_OUT)) { |