Commit c07dcd61 authored by Daniel Vetter's avatar Daniel Vetter

drm: Document device unplug infrastructure

While at it, also ocd and give them a consistent drm_dev_ prefix, like
the other device instance functionality. Plus move the functions into
the right places.
Reviewed-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20170802115604.12734-3-daniel.vetter@ffwll.ch
parent e4672e55
...@@ -291,7 +291,7 @@ struct drm_minor *drm_minor_acquire(unsigned int minor_id) ...@@ -291,7 +291,7 @@ struct drm_minor *drm_minor_acquire(unsigned int minor_id)
if (!minor) { if (!minor) {
return ERR_PTR(-ENODEV); return ERR_PTR(-ENODEV);
} else if (drm_device_is_unplugged(minor->dev)) { } else if (drm_dev_is_unplugged(minor->dev)) {
drm_dev_unref(minor->dev); drm_dev_unref(minor->dev);
return ERR_PTR(-ENODEV); return ERR_PTR(-ENODEV);
} }
...@@ -364,7 +364,22 @@ void drm_put_dev(struct drm_device *dev) ...@@ -364,7 +364,22 @@ void drm_put_dev(struct drm_device *dev)
} }
EXPORT_SYMBOL(drm_put_dev); EXPORT_SYMBOL(drm_put_dev);
void drm_unplug_dev(struct drm_device *dev) static void drm_device_set_unplugged(struct drm_device *dev)
{
smp_wmb();
atomic_set(&dev->unplugged, 1);
}
/**
* drm_dev_unplug - unplug a DRM device
* @dev: DRM device
*
* This unplugs a hotpluggable DRM device, which makes it inaccessible to
* userspace operations. Entry-points can use drm_dev_is_unplugged(). This
* essentially unregisters the device like drm_dev_unregister(), but can be
* called while there are still open users of @dev.
*/
void drm_dev_unplug(struct drm_device *dev)
{ {
/* for a USB device */ /* for a USB device */
if (drm_core_check_feature(dev, DRIVER_MODESET)) if (drm_core_check_feature(dev, DRIVER_MODESET))
...@@ -383,7 +398,7 @@ void drm_unplug_dev(struct drm_device *dev) ...@@ -383,7 +398,7 @@ void drm_unplug_dev(struct drm_device *dev)
} }
mutex_unlock(&drm_global_mutex); mutex_unlock(&drm_global_mutex);
} }
EXPORT_SYMBOL(drm_unplug_dev); EXPORT_SYMBOL(drm_dev_unplug);
/* /*
* DRM internal mount * DRM internal mount
...@@ -835,6 +850,9 @@ EXPORT_SYMBOL(drm_dev_register); ...@@ -835,6 +850,9 @@ EXPORT_SYMBOL(drm_dev_register);
* drm_dev_register() but does not deallocate the device. The caller must call * drm_dev_register() but does not deallocate the device. The caller must call
* drm_dev_unref() to drop their final reference. * drm_dev_unref() to drop their final reference.
* *
* A special form of unregistering for hotpluggable devices is drm_dev_unplug(),
* which can be called while there are still open users of @dev.
*
* This should be called first in the device teardown code to make sure * This should be called first in the device teardown code to make sure
* userspace can't access the device instance any more. * userspace can't access the device instance any more.
*/ */
......
...@@ -436,7 +436,7 @@ int drm_release(struct inode *inode, struct file *filp) ...@@ -436,7 +436,7 @@ int drm_release(struct inode *inode, struct file *filp)
if (!--dev->open_count) { if (!--dev->open_count) {
drm_lastclose(dev); drm_lastclose(dev);
if (drm_device_is_unplugged(dev)) if (drm_dev_is_unplugged(dev))
drm_put_dev(dev); drm_put_dev(dev);
} }
mutex_unlock(&drm_global_mutex); mutex_unlock(&drm_global_mutex);
......
...@@ -1001,7 +1001,7 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) ...@@ -1001,7 +1001,7 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
struct drm_vma_offset_node *node; struct drm_vma_offset_node *node;
int ret; int ret;
if (drm_device_is_unplugged(dev)) if (drm_dev_is_unplugged(dev))
return -ENODEV; return -ENODEV;
drm_vma_offset_lock_lookup(dev->vma_offset_manager); drm_vma_offset_lock_lookup(dev->vma_offset_manager);
......
...@@ -390,7 +390,7 @@ unsigned long drm_gem_cma_get_unmapped_area(struct file *filp, ...@@ -390,7 +390,7 @@ unsigned long drm_gem_cma_get_unmapped_area(struct file *filp,
struct drm_device *dev = priv->minor->dev; struct drm_device *dev = priv->minor->dev;
struct drm_vma_offset_node *node; struct drm_vma_offset_node *node;
if (drm_device_is_unplugged(dev)) if (drm_dev_is_unplugged(dev))
return -ENODEV; return -ENODEV;
drm_vma_offset_lock_lookup(dev->vma_offset_manager); drm_vma_offset_lock_lookup(dev->vma_offset_manager);
......
...@@ -716,7 +716,7 @@ long drm_ioctl_kernel(struct file *file, drm_ioctl_t *func, void *kdata, ...@@ -716,7 +716,7 @@ long drm_ioctl_kernel(struct file *file, drm_ioctl_t *func, void *kdata,
struct drm_device *dev = file_priv->minor->dev; struct drm_device *dev = file_priv->minor->dev;
int retcode; int retcode;
if (drm_device_is_unplugged(dev)) if (drm_dev_is_unplugged(dev))
return -ENODEV; return -ENODEV;
retcode = drm_ioctl_permit(flags, file_priv); retcode = drm_ioctl_permit(flags, file_priv);
...@@ -765,7 +765,7 @@ long drm_ioctl(struct file *filp, ...@@ -765,7 +765,7 @@ long drm_ioctl(struct file *filp,
dev = file_priv->minor->dev; dev = file_priv->minor->dev;
if (drm_device_is_unplugged(dev)) if (drm_dev_is_unplugged(dev))
return -ENODEV; return -ENODEV;
is_driver_ioctl = nr >= DRM_COMMAND_BASE && nr < DRM_COMMAND_END; is_driver_ioctl = nr >= DRM_COMMAND_BASE && nr < DRM_COMMAND_END;
......
...@@ -631,7 +631,7 @@ int drm_legacy_mmap(struct file *filp, struct vm_area_struct *vma) ...@@ -631,7 +631,7 @@ int drm_legacy_mmap(struct file *filp, struct vm_area_struct *vma)
struct drm_device *dev = priv->minor->dev; struct drm_device *dev = priv->minor->dev;
int ret; int ret;
if (drm_device_is_unplugged(dev)) if (drm_dev_is_unplugged(dev))
return -ENODEV; return -ENODEV;
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
......
...@@ -56,7 +56,7 @@ static const struct drm_connector_helper_funcs tinydrm_connector_hfuncs = { ...@@ -56,7 +56,7 @@ static const struct drm_connector_helper_funcs tinydrm_connector_hfuncs = {
static enum drm_connector_status static enum drm_connector_status
tinydrm_connector_detect(struct drm_connector *connector, bool force) tinydrm_connector_detect(struct drm_connector *connector, bool force)
{ {
if (drm_device_is_unplugged(connector->dev)) if (drm_dev_is_unplugged(connector->dev))
return connector_status_disconnected; return connector_status_disconnected;
return connector->status; return connector->status;
......
...@@ -96,7 +96,7 @@ static int udl_mode_valid(struct drm_connector *connector, ...@@ -96,7 +96,7 @@ static int udl_mode_valid(struct drm_connector *connector,
static enum drm_connector_status static enum drm_connector_status
udl_detect(struct drm_connector *connector, bool force) udl_detect(struct drm_connector *connector, bool force)
{ {
if (drm_device_is_unplugged(connector->dev)) if (drm_dev_is_unplugged(connector->dev))
return connector_status_disconnected; return connector_status_disconnected;
return connector_status_connected; return connector_status_connected;
} }
......
...@@ -102,7 +102,7 @@ static void udl_usb_disconnect(struct usb_interface *interface) ...@@ -102,7 +102,7 @@ static void udl_usb_disconnect(struct usb_interface *interface)
drm_kms_helper_poll_disable(dev); drm_kms_helper_poll_disable(dev);
udl_fbdev_unplug(dev); udl_fbdev_unplug(dev);
udl_drop_usb(dev); udl_drop_usb(dev);
drm_unplug_dev(dev); drm_dev_unplug(dev);
} }
/* /*
......
...@@ -198,7 +198,7 @@ static int udl_fb_open(struct fb_info *info, int user) ...@@ -198,7 +198,7 @@ static int udl_fb_open(struct fb_info *info, int user)
struct udl_device *udl = dev->dev_private; struct udl_device *udl = dev->dev_private;
/* If the USB device is gone, we don't accept new opens */ /* If the USB device is gone, we don't accept new opens */
if (drm_device_is_unplugged(udl->ddev)) if (drm_dev_is_unplugged(udl->ddev))
return -ENODEV; return -ENODEV;
ufbdev->fb_count++; ufbdev->fb_count++;
......
...@@ -320,19 +320,6 @@ static __inline__ int drm_core_check_feature(struct drm_device *dev, ...@@ -320,19 +320,6 @@ static __inline__ int drm_core_check_feature(struct drm_device *dev,
return ((dev->driver->driver_features & feature) ? 1 : 0); return ((dev->driver->driver_features & feature) ? 1 : 0);
} }
static inline void drm_device_set_unplugged(struct drm_device *dev)
{
smp_wmb();
atomic_set(&dev->unplugged, 1);
}
static inline int drm_device_is_unplugged(struct drm_device *dev)
{
int ret = atomic_read(&dev->unplugged);
smp_rmb();
return ret;
}
/******************************************************************/ /******************************************************************/
/** \name Internal function definitions */ /** \name Internal function definitions */
/*@{*/ /*@{*/
......
...@@ -30,7 +30,8 @@ ...@@ -30,7 +30,8 @@
#include <linux/list.h> #include <linux/list.h>
#include <linux/irqreturn.h> #include <linux/irqreturn.h>
struct drm_device; #include <drm/drm_device.h>
struct drm_file; struct drm_file;
struct drm_gem_object; struct drm_gem_object;
struct drm_master; struct drm_master;
...@@ -613,7 +614,24 @@ void drm_dev_unregister(struct drm_device *dev); ...@@ -613,7 +614,24 @@ void drm_dev_unregister(struct drm_device *dev);
void drm_dev_ref(struct drm_device *dev); void drm_dev_ref(struct drm_device *dev);
void drm_dev_unref(struct drm_device *dev); void drm_dev_unref(struct drm_device *dev);
void drm_put_dev(struct drm_device *dev); void drm_put_dev(struct drm_device *dev);
void drm_unplug_dev(struct drm_device *dev); void drm_dev_unplug(struct drm_device *dev);
/**
* drm_dev_is_unplugged - is a DRM device unplugged
* @dev: DRM device
*
* This function can be called to check whether a hotpluggable is unplugged.
* Unplugging itself is singalled through drm_dev_unplug(). If a device is
* unplugged, these two functions guarantee that any store before calling
* drm_dev_unplug() is visible to callers of this function after it completes
*/
static inline int drm_dev_is_unplugged(struct drm_device *dev)
{
int ret = atomic_read(&dev->unplugged);
smp_rmb();
return ret;
}
int drm_dev_set_unique(struct drm_device *dev, const char *name); int drm_dev_set_unique(struct drm_device *dev, const char *name);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment