All of lore.kernel.org
 help / color / mirror / Atom feed
From: Haixia Shi <hshi@chromium.org>
To: David Herrmann <dh.herrmann@gmail.com>
Cc: "dri-devel@lists.freedesktop.org" <dri-devel@lists.freedesktop.org>
Subject: Re: [PATCH 2/2] drm: make unplugged flag specific to udl driver
Date: Wed, 10 Feb 2016 12:39:53 -0800	[thread overview]
Message-ID: <CALH7+PifH7P2_wGuqw1gULeNxaG3Mg63ME25BcqeYjT8NExrrQ@mail.gmail.com> (raw)
In-Reply-To: <CANq1E4SUU_pyiTMTnwa8EkCgN1LoKBHKYBhSdruMGtCCjdLO-w@mail.gmail.com>


[-- Attachment #1.1: Type: text/plain, Size: 14744 bytes --]

> +       if (udl_device_is_unplugged(dev) &&
> +               nr != DRM_IOCTL_NR(DRM_IOCTL_MODE_SETCRTC) &&
> +               nr != DRM_IOCTL_NR(DRM_IOCTL_MODE_RMFB) &&
> +               nr != DRM_IOCTL_NR(DRM_IOCTL_MODE_DESTROY_DUMB))
> +               return -ENODEV;
>
>Why?
>
>Just do:
>
>        if (udl_device_is_unplugged(dev))
>                return -ENODEV;
>
>Why this complex logic here?

Because there are legitimate ioctl calls after UDL is unplugged. See
crbug.com/583508 and crbug.com/583758 for some background.

The userspace (Chrome in this case) has allocated FBs and Dumb buffers on
the drm device and needs to be given a chance to properly deallocate them
(via RMFB and DESTROY_DUMB). In addition, it needs to call SETCRTC with
fb_id = 0 to properly release the last refcount on the primary fb.

I initially proposed adding an "UNPLUG_DISALLOW" flag to ioctls so that we
can whitelist them on a case-by-case basis but that proposal got shot down
as being unnecessary, but you can see my original patch at
https://chromium-review.googlesource.com/#/c/326160/


On Wed, Feb 10, 2016 at 4:24 AM, David Herrmann <dh.herrmann@gmail.com>
wrote:

> Hi
>
> On Tue, Feb 9, 2016 at 10:05 PM, Haixia Shi <hshi@chromium.org> wrote:
> > Remove the general drm_device_is_unplugged() checks, and move the
> unplugged
> > flag handling logic into drm/udl. In general we want to keep
> driver-specific
> > logic out of common drm code.
> >
> > Signed-off-by: Haixia Shi <hshi@chromium.org>
> > Reviewed-by: Stéphane Marchesin <marcheu@chromium.org>
> > ---
> >  drivers/gpu/drm/drm_drv.c           |  6 ----
> >  drivers/gpu/drm/drm_fops.c          |  2 --
> >  drivers/gpu/drm/drm_gem.c           |  3 --
> >  drivers/gpu/drm/drm_ioctl.c         |  3 --
> >  drivers/gpu/drm/drm_vm.c            |  3 --
> >  drivers/gpu/drm/udl/udl_connector.c |  2 +-
> >  drivers/gpu/drm/udl/udl_drv.c       |  7 +++--
> >  drivers/gpu/drm/udl/udl_drv.h       |  6 ++++
> >  drivers/gpu/drm/udl/udl_fb.c        |  2 +-
> >  drivers/gpu/drm/udl/udl_gem.c       |  5 +++
> >  drivers/gpu/drm/udl/udl_main.c      | 61
> +++++++++++++++++++++++++++++++++++++
> >  include/drm/drmP.h                  | 14 ---------
> >  12 files changed, 78 insertions(+), 36 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
> > index 167c8d3..f93ee12 100644
> > --- a/drivers/gpu/drm/drm_drv.c
> > +++ b/drivers/gpu/drm/drm_drv.c
> > @@ -376,9 +376,6 @@ struct drm_minor *drm_minor_acquire(unsigned int
> minor_id)
> >
> >         if (!minor) {
> >                 return ERR_PTR(-ENODEV);
> > -       } else if (drm_device_is_unplugged(minor->dev)) {
> > -               drm_dev_unref(minor->dev);
> > -               return ERR_PTR(-ENODEV);
> >         }
> >
> >         return minor;
> > @@ -464,9 +461,6 @@ void drm_unplug_dev(struct drm_device *dev)
> >         drm_minor_unregister(dev, DRM_MINOR_CONTROL);
> >
> >         mutex_lock(&drm_global_mutex);
> > -
> > -       drm_device_set_unplugged(dev);
> > -
> >         if (dev->open_count == 0) {
> >                 drm_put_dev(dev);
> >         }
> > diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
> > index 1ea8790..b4332d4 100644
> > --- a/drivers/gpu/drm/drm_fops.c
> > +++ b/drivers/gpu/drm/drm_fops.c
> > @@ -497,8 +497,6 @@ int drm_release(struct inode *inode, struct file
> *filp)
> >
> >         if (!--dev->open_count) {
> >                 retcode = drm_lastclose(dev);
> > -               if (drm_device_is_unplugged(dev))
> > -                       drm_put_dev(dev);
> >         }
> >         mutex_unlock(&drm_global_mutex);
> >
> > diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
> > index 2e8c77e..c622e32 100644
> > --- a/drivers/gpu/drm/drm_gem.c
> > +++ b/drivers/gpu/drm/drm_gem.c
> > @@ -900,9 +900,6 @@ int drm_gem_mmap(struct file *filp, struct
> vm_area_struct *vma)
> >         struct drm_vma_offset_node *node;
> >         int ret;
> >
> > -       if (drm_device_is_unplugged(dev))
> > -               return -ENODEV;
> > -
> >         drm_vma_offset_lock_lookup(dev->vma_offset_manager);
> >         node =
> drm_vma_offset_exact_lookup_locked(dev->vma_offset_manager,
> >                                                   vma->vm_pgoff,
> > diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
> > index 8ce2a0c..f959074 100644
> > --- a/drivers/gpu/drm/drm_ioctl.c
> > +++ b/drivers/gpu/drm/drm_ioctl.c
> > @@ -695,9 +695,6 @@ long drm_ioctl(struct file *filp,
> >
> >         dev = file_priv->minor->dev;
> >
> > -       if (drm_device_is_unplugged(dev))
> > -               return -ENODEV;
> > -
> >         is_driver_ioctl = nr >= DRM_COMMAND_BASE && nr < DRM_COMMAND_END;
> >
> >         if (is_driver_ioctl) {
> > diff --git a/drivers/gpu/drm/drm_vm.c b/drivers/gpu/drm/drm_vm.c
> > index f90bd5f..3a68be4 100644
> > --- a/drivers/gpu/drm/drm_vm.c
> > +++ b/drivers/gpu/drm/drm_vm.c
> > @@ -657,9 +657,6 @@ int drm_legacy_mmap(struct file *filp, struct
> vm_area_struct *vma)
> >         struct drm_device *dev = priv->minor->dev;
> >         int ret;
> >
> > -       if (drm_device_is_unplugged(dev))
> > -               return -ENODEV;
> > -
> >         mutex_lock(&dev->struct_mutex);
> >         ret = drm_mmap_locked(filp, vma);
> >         mutex_unlock(&dev->struct_mutex);
> > diff --git a/drivers/gpu/drm/udl/udl_connector.c
> b/drivers/gpu/drm/udl/udl_connector.c
> > index 4709b54..b168f2c 100644
> > --- a/drivers/gpu/drm/udl/udl_connector.c
> > +++ b/drivers/gpu/drm/udl/udl_connector.c
> > @@ -96,7 +96,7 @@ static int udl_mode_valid(struct drm_connector
> *connector,
> >  static enum drm_connector_status
> >  udl_detect(struct drm_connector *connector, bool force)
> >  {
> > -       if (drm_device_is_unplugged(connector->dev))
> > +       if (udl_device_is_unplugged(connector->dev))
> >                 return connector_status_disconnected;
> >         return connector_status_connected;
> >  }
> > diff --git a/drivers/gpu/drm/udl/udl_drv.c
> b/drivers/gpu/drm/udl/udl_drv.c
> > index d5728ec..f5c2a97 100644
> > --- a/drivers/gpu/drm/udl/udl_drv.c
> > +++ b/drivers/gpu/drm/udl/udl_drv.c
> > @@ -24,12 +24,12 @@ static const struct vm_operations_struct
> udl_gem_vm_ops = {
> >
> >  static const struct file_operations udl_driver_fops = {
> >         .owner = THIS_MODULE,
> > -       .open = drm_open,
> > +       .open = udl_drm_open,
> >         .mmap = udl_drm_gem_mmap,
> >         .poll = drm_poll,
> >         .read = drm_read,
> > -       .unlocked_ioctl = drm_ioctl,
> > -       .release = drm_release,
> > +       .unlocked_ioctl = udl_drm_ioctl,
> > +       .release = udl_drm_release,
> >  #ifdef CONFIG_COMPAT
> >         .compat_ioctl = drm_compat_ioctl,
> >  #endif
> > @@ -97,6 +97,7 @@ static void udl_usb_disconnect(struct usb_interface
> *interface)
> >         drm_connector_unplug_all(dev);
> >         udl_fbdev_unplug(dev);
> >         udl_drop_usb(dev);
> > +       udl_device_set_unplugged(dev);
> >         drm_unplug_dev(dev);
> >  }
> >
> > diff --git a/drivers/gpu/drm/udl/udl_drv.h
> b/drivers/gpu/drm/udl/udl_drv.h
> > index 4a064ef..75aa91c 100644
> > --- a/drivers/gpu/drm/udl/udl_drv.h
> > +++ b/drivers/gpu/drm/udl/udl_drv.h
> > @@ -65,6 +65,7 @@ struct udl_device {
> >         atomic_t bytes_identical; /* saved effort with backbuffer
> comparison */
> >         atomic_t bytes_sent; /* to usb, after compression including
> overhead */
> >         atomic_t cpu_kcycles_used; /* transpired during pixel processing
> */
> > +       atomic_t unplugged; /* device has been unplugged or gone away */
> >  };
> >
> >  struct udl_gem_object {
> > @@ -133,6 +134,9 @@ int udl_gem_get_pages(struct udl_gem_object *obj);
> >  void udl_gem_put_pages(struct udl_gem_object *obj);
> >  int udl_gem_vmap(struct udl_gem_object *obj);
> >  void udl_gem_vunmap(struct udl_gem_object *obj);
> > +int udl_drm_open(struct inode *inode, struct file *filp);
> > +int udl_drm_release(struct inode *inode, struct file *filp);
> > +int udl_drm_ioctl(struct file *filp, unsigned int cmd, unsigned long
> arg);
> >  int udl_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma);
> >  int udl_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
> >
> > @@ -140,6 +144,8 @@ int udl_handle_damage(struct udl_framebuffer *fb,
> int x, int y,
> >                       int width, int height);
> >
> >  int udl_drop_usb(struct drm_device *dev);
> > +void udl_device_set_unplugged(struct drm_device *dev);
> > +int udl_device_is_unplugged(struct drm_device *dev);
> >
> >  #define CMD_WRITE_RAW8   "\xAF\x60" /**< 8 bit raw write command. */
> >  #define CMD_WRITE_RL8    "\xAF\x61" /**< 8 bit run length command. */
> > diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c
> > index 200419d..df1d53e 100644
> > --- a/drivers/gpu/drm/udl/udl_fb.c
> > +++ b/drivers/gpu/drm/udl/udl_fb.c
> > @@ -325,7 +325,7 @@ static int udl_fb_open(struct fb_info *info, int
> user)
> >         struct udl_device *udl = dev->dev_private;
> >
> >         /* If the USB device is gone, we don't accept new opens */
> > -       if (drm_device_is_unplugged(udl->ddev))
> > +       if (udl_device_is_unplugged(udl->ddev))
> >                 return -ENODEV;
> >
> >         ufbdev->fb_count++;
> > diff --git a/drivers/gpu/drm/udl/udl_gem.c
> b/drivers/gpu/drm/udl/udl_gem.c
> > index 2a0a784..33c302f 100644
> > --- a/drivers/gpu/drm/udl/udl_gem.c
> > +++ b/drivers/gpu/drm/udl/udl_gem.c
> > @@ -86,8 +86,13 @@ int udl_dumb_create(struct drm_file *file,
> >
> >  int udl_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
> >  {
> > +       struct drm_file *priv = filp->private_data;
> > +       struct drm_device *dev = priv->minor->dev;
> >         int ret;
> >
> > +       if (udl_device_is_unplugged(dev))
> > +               return -ENODEV;
> > +
> >         ret = drm_gem_mmap(filp, vma);
> >         if (ret)
> >                 return ret;
> > diff --git a/drivers/gpu/drm/udl/udl_main.c
> b/drivers/gpu/drm/udl/udl_main.c
> > index 33dbfb2..2ba3ee3 100644
> > --- a/drivers/gpu/drm/udl/udl_main.c
> > +++ b/drivers/gpu/drm/udl/udl_main.c
> > @@ -350,3 +350,64 @@ int udl_driver_unload(struct drm_device *dev)
> >         kfree(udl);
> >         return 0;
> >  }
> > +
> > +int udl_drm_open(struct inode *inode, struct file *filp)
> > +{
> > +       struct drm_file *file_priv;
> > +       struct drm_minor *minor;
> > +
> > +       int ret = drm_open(inode, filp);
> > +       if (ret)
> > +               return ret;
> > +
> > +       file_priv = filp->private_data;
> > +       minor = file_priv->minor;
> > +       if (udl_device_is_unplugged(minor->dev)) {
> > +               drm_dev_unref(minor->dev);
> > +               return -ENODEV;
> > +       }
>
> This doesn't make sense to me. You're called here with global-mutex
> held, so you can just check udl_device_is_unplugged() before calling
> into drm_open().
>
> > +
> > +       return 0;
> > +}
> > +
> > +int udl_drm_release(struct inode *inode, struct file *filp)
> > +{
> > +       struct drm_file *file_priv = filp->private_data;
> > +       struct drm_device *dev = file_priv->minor->dev;
> > +
> > +       int ret = drm_release(inode, filp);
> > +       if (!dev->open_count && udl_device_is_unplugged(dev))
> > +               drm_put_dev(dev);
>
> This should rather be:
>
>         drm_release(inode, filp);
>         mutex_lock(&drm_global_mutex);
>         if (!dev->open_count && udl_device_is_unplugged(dev))
>                 drm_put_dev(dev);
>         mutex_unlock(&drm_global_mutex);
>
>         return 0;
>
> There is no reason to look at the return code of drm_release(), ever.
>
> > +
> > +       return ret;
> > +}
> > +
> > +int udl_drm_ioctl(struct file *filp, unsigned int cmd, unsigned long
> arg)
> > +{
> > +       struct drm_file *file_priv = filp->private_data;
> > +       struct drm_device *dev = file_priv->minor->dev;
> > +       unsigned int nr = DRM_IOCTL_NR(cmd);
> > +
> > +       if (udl_device_is_unplugged(dev) &&
> > +               nr != DRM_IOCTL_NR(DRM_IOCTL_MODE_SETCRTC) &&
> > +               nr != DRM_IOCTL_NR(DRM_IOCTL_MODE_RMFB) &&
> > +               nr != DRM_IOCTL_NR(DRM_IOCTL_MODE_DESTROY_DUMB))
> > +               return -ENODEV;
>
> Why?
>
> Just do:
>
>         if (udl_device_is_unplugged(dev))
>                 return -ENODEV;
>
> Why this complex logic here?
>
> Thanks
> David
>
> > +
> > +       return drm_ioctl(filp, cmd, arg);
> > +}
> > +
> > +void udl_device_set_unplugged(struct drm_device *dev)
> > +{
> > +       struct udl_device *udl = dev->dev_private;
> > +       smp_wmb();
> > +       atomic_set(&udl->unplugged, 1);
> > +}
> > +
> > +int udl_device_is_unplugged(struct drm_device *dev)
> > +{
> > +       struct udl_device *udl = dev->dev_private;
> > +       int ret = atomic_read(&udl->unplugged);
> > +       smp_rmb();
> > +       return ret;
> > +}
> > diff --git a/include/drm/drmP.h b/include/drm/drmP.h
> > index d7162cf..40c6099 100644
> > --- a/include/drm/drmP.h
> > +++ b/include/drm/drmP.h
> > @@ -748,7 +748,6 @@ struct drm_device {
> >         struct drm_minor *control;              /**< Control node */
> >         struct drm_minor *primary;              /**< Primary node */
> >         struct drm_minor *render;               /**< Render node */
> > -       atomic_t unplugged;                     /**< Flag whether dev is
> dead */
> >         struct inode *anon_inode;               /**< inode for private
> address-space */
> >         char *unique;                           /**< unique name of the
> device */
> >         /*@} */
> > @@ -879,19 +878,6 @@ static __inline__ int drm_core_check_feature(struct
> drm_device *dev,
> >         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;
> > -}
> > -
> >  static inline bool drm_is_render_client(const struct drm_file
> *file_priv)
> >  {
> >         return file_priv->minor->type == DRM_MINOR_RENDER;
> > --
> > 2.7.0.rc3.207.g0ac5344
> >
>

[-- Attachment #1.2: Type: text/html, Size: 18538 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

  reply	other threads:[~2016-02-10 20:39 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-02-05 21:57 [PATCH 1/2] drm/msm: remove the drm_device_is_unplugged check Haixia Shi
2016-02-05 21:57 ` [PATCH 2/2] drm: make unplugged flag specific to udl driver Haixia Shi
2016-02-09 12:44   ` David Herrmann
2016-02-09 20:45     ` Haixia Shi
2016-02-09 20:52       ` David Herrmann
2016-02-10 23:16   ` [PATCH v2 2/2] drm: remove drm_device_is_unplugged checks in common drm code Haixia Shi
2016-02-09 10:25 ` [PATCH 1/2] drm/msm: remove the drm_device_is_unplugged check David Herrmann
2016-02-09 13:03   ` Daniel Vetter
2016-02-09 21:05 ` [PATCH 2/2] drm: make unplugged flag specific to udl driver Haixia Shi
2016-02-10  6:27   ` Daniel Vetter
2016-02-10 12:24   ` David Herrmann
2016-02-10 20:39     ` Haixia Shi [this message]
2016-02-10 21:38       ` David Herrmann
2016-02-10 21:46         ` Stéphane Marchesin
2016-02-10 21:54           ` David Herrmann
2016-02-10 22:02             ` Stéphane Marchesin
2016-02-10 22:09               ` David Herrmann
2016-02-11  8:17               ` Daniel Vetter
2016-02-10 20:51     ` Haixia Shi
2016-02-10 21:00       ` Haixia Shi
2016-02-10 21:33         ` David Herrmann
2016-02-10 21:35       ` David Herrmann
2016-02-10 21:38         ` Haixia Shi
2016-02-10 21:40           ` David Herrmann
2016-02-10 23:18 ` [PATCH v2 2/2] drm: remove drm_device_is_unplugged checks in common drm code Haixia Shi
2016-02-11  8:19   ` Daniel Vetter
2016-02-11 10:30   ` David Herrmann
2016-02-11 19:19     ` Haixia Shi
2016-02-11 21:57     ` [PATCH v3 2/2] drm: remove drm_device_is_unplugged and related code Haixia Shi
2016-02-12  6:22       ` Daniel Vetter
2016-02-12 19:50       ` Haixia Shi
2016-02-17  0:27         ` Haixia Shi
2016-02-26 14:29         ` David Herrmann

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CALH7+PifH7P2_wGuqw1gULeNxaG3Mg63ME25BcqeYjT8NExrrQ@mail.gmail.com \
    --to=hshi@chromium.org \
    --cc=dh.herrmann@gmail.com \
    --cc=dri-devel@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.