aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/drm_drv.c4
-rw-r--r--drivers/gpu/drm/drm_fops.c8
-rw-r--r--drivers/gpu/drm/drm_gem.c3
-rw-r--r--drivers/gpu/drm/drm_stub.c23
-rw-r--r--drivers/gpu/drm/drm_vm.c3
-rw-r--r--include/drm/drmP.h16
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
432static 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}
494EXPORT_SYMBOL(drm_put_dev); 499EXPORT_SYMBOL(drm_put_dev);
500
501void 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}
517EXPORT_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
1240static inline void drm_device_set_unplugged(struct drm_device *dev)
1241{
1242 smp_wmb();
1243 atomic_set(&dev->unplugged, 1);
1244}
1245
1246static 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
1456extern void drm_put_dev(struct drm_device *dev); 1471extern void drm_put_dev(struct drm_device *dev);
1457extern int drm_put_minor(struct drm_minor **minor); 1472extern int drm_put_minor(struct drm_minor **minor);
1473extern void drm_unplug_dev(struct drm_device *dev);
1458extern unsigned int drm_debug; 1474extern unsigned int drm_debug;
1459 1475
1460extern unsigned int drm_vblank_offdelay; 1476extern unsigned int drm_vblank_offdelay;