diff options
-rw-r--r-- | drivers/gpu/drm/drm_drv.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_fops.c | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_gem.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_stub.c | 23 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_vm.c | 3 | ||||
-rw-r--r-- | include/drm/drmP.h | 16 |
6 files changed, 57 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index d166bd080400..0b65fbc8a630 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c | |||
@@ -390,6 +390,10 @@ long drm_ioctl(struct file *filp, | |||
390 | unsigned int usize, asize; | 390 | unsigned int usize, asize; |
391 | 391 | ||
392 | dev = file_priv->minor->dev; | 392 | dev = file_priv->minor->dev; |
393 | |||
394 | if (drm_device_is_unplugged(dev)) | ||
395 | return -ENODEV; | ||
396 | |||
393 | atomic_inc(&dev->ioctl_count); | 397 | atomic_inc(&dev->ioctl_count); |
394 | atomic_inc(&dev->counts[_DRM_STAT_IOCTLS]); | 398 | atomic_inc(&dev->counts[_DRM_STAT_IOCTLS]); |
395 | ++file_priv->ioctl_count; | 399 | ++file_priv->ioctl_count; |
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 6263b0147598..7348a3dab250 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c | |||
@@ -133,6 +133,9 @@ int drm_open(struct inode *inode, struct file *filp) | |||
133 | if (!(dev = minor->dev)) | 133 | if (!(dev = minor->dev)) |
134 | return -ENODEV; | 134 | return -ENODEV; |
135 | 135 | ||
136 | if (drm_device_is_unplugged(dev)) | ||
137 | return -ENODEV; | ||
138 | |||
136 | retcode = drm_open_helper(inode, filp, dev); | 139 | retcode = drm_open_helper(inode, filp, dev); |
137 | if (!retcode) { | 140 | if (!retcode) { |
138 | atomic_inc(&dev->counts[_DRM_STAT_OPENS]); | 141 | atomic_inc(&dev->counts[_DRM_STAT_OPENS]); |
@@ -181,6 +184,9 @@ int drm_stub_open(struct inode *inode, struct file *filp) | |||
181 | if (!(dev = minor->dev)) | 184 | if (!(dev = minor->dev)) |
182 | goto out; | 185 | goto out; |
183 | 186 | ||
187 | if (drm_device_is_unplugged(dev)) | ||
188 | goto out; | ||
189 | |||
184 | old_fops = filp->f_op; | 190 | old_fops = filp->f_op; |
185 | filp->f_op = fops_get(dev->driver->fops); | 191 | filp->f_op = fops_get(dev->driver->fops); |
186 | if (filp->f_op == NULL) { | 192 | if (filp->f_op == NULL) { |
@@ -579,6 +585,8 @@ int drm_release(struct inode *inode, struct file *filp) | |||
579 | retcode = -EBUSY; | 585 | retcode = -EBUSY; |
580 | } else | 586 | } else |
581 | retcode = drm_lastclose(dev); | 587 | retcode = drm_lastclose(dev); |
588 | if (drm_device_is_unplugged(dev)) | ||
589 | drm_put_dev(dev); | ||
582 | } | 590 | } |
583 | mutex_unlock(&drm_global_mutex); | 591 | mutex_unlock(&drm_global_mutex); |
584 | 592 | ||
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index 3ebe3c8f58b5..0ef358e53245 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c | |||
@@ -661,6 +661,9 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) | |||
661 | struct drm_hash_item *hash; | 661 | struct drm_hash_item *hash; |
662 | int ret = 0; | 662 | int ret = 0; |
663 | 663 | ||
664 | if (drm_device_is_unplugged(dev)) | ||
665 | return -ENODEV; | ||
666 | |||
664 | mutex_lock(&dev->struct_mutex); | 667 | mutex_lock(&dev->struct_mutex); |
665 | 668 | ||
666 | if (drm_ht_find_item(&mm->offset_hash, vma->vm_pgoff, &hash)) { | 669 | if (drm_ht_find_item(&mm->offset_hash, vma->vm_pgoff, &hash)) { |
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index 6d7b083c5b77..bbd40eaf9821 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c | |||
@@ -429,6 +429,11 @@ int drm_put_minor(struct drm_minor **minor_p) | |||
429 | return 0; | 429 | return 0; |
430 | } | 430 | } |
431 | 431 | ||
432 | static void drm_unplug_minor(struct drm_minor *minor) | ||
433 | { | ||
434 | drm_sysfs_device_remove(minor); | ||
435 | } | ||
436 | |||
432 | /** | 437 | /** |
433 | * Called via drm_exit() at module unload time or when pci device is | 438 | * Called via drm_exit() at module unload time or when pci device is |
434 | * unplugged. | 439 | * unplugged. |
@@ -492,3 +497,21 @@ void drm_put_dev(struct drm_device *dev) | |||
492 | kfree(dev); | 497 | kfree(dev); |
493 | } | 498 | } |
494 | EXPORT_SYMBOL(drm_put_dev); | 499 | EXPORT_SYMBOL(drm_put_dev); |
500 | |||
501 | void drm_unplug_dev(struct drm_device *dev) | ||
502 | { | ||
503 | /* for a USB device */ | ||
504 | if (drm_core_check_feature(dev, DRIVER_MODESET)) | ||
505 | drm_unplug_minor(dev->control); | ||
506 | drm_unplug_minor(dev->primary); | ||
507 | |||
508 | mutex_lock(&drm_global_mutex); | ||
509 | |||
510 | drm_device_set_unplugged(dev); | ||
511 | |||
512 | if (dev->open_count == 0) { | ||
513 | drm_put_dev(dev); | ||
514 | } | ||
515 | mutex_unlock(&drm_global_mutex); | ||
516 | } | ||
517 | EXPORT_SYMBOL(drm_unplug_dev); | ||
diff --git a/drivers/gpu/drm/drm_vm.c b/drivers/gpu/drm/drm_vm.c index 55cd61567812..149561818349 100644 --- a/drivers/gpu/drm/drm_vm.c +++ b/drivers/gpu/drm/drm_vm.c | |||
@@ -680,6 +680,9 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) | |||
680 | struct drm_device *dev = priv->minor->dev; | 680 | struct drm_device *dev = priv->minor->dev; |
681 | int ret; | 681 | int ret; |
682 | 682 | ||
683 | if (drm_device_is_unplugged(dev)) | ||
684 | return -ENODEV; | ||
685 | |||
683 | mutex_lock(&dev->struct_mutex); | 686 | mutex_lock(&dev->struct_mutex); |
684 | ret = drm_mmap_locked(filp, vma); | 687 | ret = drm_mmap_locked(filp, vma); |
685 | mutex_unlock(&dev->struct_mutex); | 688 | mutex_unlock(&dev->struct_mutex); |
diff --git a/include/drm/drmP.h b/include/drm/drmP.h index cfd921ff0cc4..574bd1c81ebd 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h | |||
@@ -1170,6 +1170,8 @@ struct drm_device { | |||
1170 | struct idr object_name_idr; | 1170 | struct idr object_name_idr; |
1171 | /*@} */ | 1171 | /*@} */ |
1172 | int switch_power_state; | 1172 | int switch_power_state; |
1173 | |||
1174 | atomic_t unplugged; /* device has been unplugged or gone away */ | ||
1173 | }; | 1175 | }; |
1174 | 1176 | ||
1175 | #define DRM_SWITCH_POWER_ON 0 | 1177 | #define DRM_SWITCH_POWER_ON 0 |
@@ -1235,6 +1237,19 @@ static inline int drm_mtrr_del(int handle, unsigned long offset, | |||
1235 | } | 1237 | } |
1236 | #endif | 1238 | #endif |
1237 | 1239 | ||
1240 | static inline void drm_device_set_unplugged(struct drm_device *dev) | ||
1241 | { | ||
1242 | smp_wmb(); | ||
1243 | atomic_set(&dev->unplugged, 1); | ||
1244 | } | ||
1245 | |||
1246 | static inline int drm_device_is_unplugged(struct drm_device *dev) | ||
1247 | { | ||
1248 | int ret = atomic_read(&dev->unplugged); | ||
1249 | smp_rmb(); | ||
1250 | return ret; | ||
1251 | } | ||
1252 | |||
1238 | /******************************************************************/ | 1253 | /******************************************************************/ |
1239 | /** \name Internal function definitions */ | 1254 | /** \name Internal function definitions */ |
1240 | /*@{*/ | 1255 | /*@{*/ |
@@ -1455,6 +1470,7 @@ extern void drm_master_put(struct drm_master **master); | |||
1455 | 1470 | ||
1456 | extern void drm_put_dev(struct drm_device *dev); | 1471 | extern void drm_put_dev(struct drm_device *dev); |
1457 | extern int drm_put_minor(struct drm_minor **minor); | 1472 | extern int drm_put_minor(struct drm_minor **minor); |
1473 | extern void drm_unplug_dev(struct drm_device *dev); | ||
1458 | extern unsigned int drm_debug; | 1474 | extern unsigned int drm_debug; |
1459 | 1475 | ||
1460 | extern unsigned int drm_vblank_offdelay; | 1476 | extern unsigned int drm_vblank_offdelay; |