diff mbox

[2/2] drm/udl: implement usb_driver suspend/resume.

Message ID 1472593821-38429-2-git-send-email-hshi@chromium.org (mailing list archive)
State New, archived
Headers show

Commit Message

Haixia Shi Aug. 30, 2016, 9:50 p.m. UTC
The usb_driver suspend and resume function pointers must be populated
to prevent forced unbinding of USB interface driver. See usb/core/driver.c:
unbind_no_pm_drivers_interfaces().

Restore mode and damage the entire frame buffer upon resume.

TEST=suspend and resume with the same UDL device connected
TEST=suspend with UDL, unplug UDL and resume
TEST=suspend with UDL, unplug and connect another UDL device then resume

Signed-off-by: Haixia Shi <hshi@chromium.org>
Reviewed-by: Stphane Marchesin <marcheu@chromium.org>
---
 drivers/gpu/drm/udl/udl_drv.c     | 17 +++++++++++++++++
 drivers/gpu/drm/udl/udl_drv.h     |  2 ++
 drivers/gpu/drm/udl/udl_modeset.c | 13 +++++++++++++
 3 files changed, 32 insertions(+)

Comments

Sean Paul Sept. 6, 2016, 6:02 p.m. UTC | #1
On Tue, Aug 30, 2016 at 5:50 PM, Haixia Shi <hshi@chromium.org> wrote:
> The usb_driver suspend and resume function pointers must be populated
> to prevent forced unbinding of USB interface driver. See usb/core/driver.c:
> unbind_no_pm_drivers_interfaces().
>
> Restore mode and damage the entire frame buffer upon resume.
>
> TEST=suspend and resume with the same UDL device connected
> TEST=suspend with UDL, unplug UDL and resume
> TEST=suspend with UDL, unplug and connect another UDL device then resume
>
> Signed-off-by: Haixia Shi <hshi@chromium.org>
> Reviewed-by: Stphane Marchesin <marcheu@chromium.org>

I think this patch stands well on its own, and given the work required for 1/2:

I took the liberty of fixing your checkpatch warnings and gave marcheu
his é back.

Applied to drm-misc

Sean


> ---
>  drivers/gpu/drm/udl/udl_drv.c     | 17 +++++++++++++++++
>  drivers/gpu/drm/udl/udl_drv.h     |  2 ++
>  drivers/gpu/drm/udl/udl_modeset.c | 13 +++++++++++++
>  3 files changed, 32 insertions(+)
>
> diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c
> index 17d34e0..e5dc73b 100644
> --- a/drivers/gpu/drm/udl/udl_drv.c
> +++ b/drivers/gpu/drm/udl/udl_drv.c
> @@ -16,6 +16,21 @@ static int udl_driver_set_busid(struct drm_device *d, struct drm_master *m)
>         return 0;
>  }
>
> +static int udl_usb_suspend(struct usb_interface *interface,
> +                          pm_message_t message)
> +{
> +       return 0;
> +}
> +
> +static int udl_usb_resume(struct usb_interface *interface)
> +{
> +       struct drm_device *dev = usb_get_intfdata(interface);
> +
> +       udl_modeset_restore(dev);
> +       return 0;
> +}
> +
> +
>  static const struct vm_operations_struct udl_gem_vm_ops = {
>         .fault = udl_gem_fault,
>         .open = drm_gem_vm_open,
> @@ -122,6 +137,8 @@ static struct usb_driver udl_driver = {
>         .name = "udl",
>         .probe = udl_usb_probe,
>         .disconnect = udl_usb_disconnect,
> +       .suspend = udl_usb_suspend,
> +       .resume = udl_usb_resume,
>         .id_table = id_table,
>  };
>  module_usb_driver(udl_driver);
> diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h
> index 0b03d34..f338a57 100644
> --- a/drivers/gpu/drm/udl/udl_drv.h
> +++ b/drivers/gpu/drm/udl/udl_drv.h
> @@ -52,6 +52,7 @@ struct udl_device {
>         struct device *dev;
>         struct drm_device *ddev;
>         struct usb_device *udev;
> +       struct drm_crtc *crtc;
>
>         int sku_pixel_limit;
>
> @@ -87,6 +88,7 @@ struct udl_framebuffer {
>
>  /* modeset */
>  int udl_modeset_init(struct drm_device *dev);
> +void udl_modeset_restore(struct drm_device *dev);
>  void udl_modeset_cleanup(struct drm_device *dev);
>  int udl_connector_init(struct drm_device *dev, struct drm_encoder *encoder);
>
> diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c
> index 7369512..69d6a4f 100644
> --- a/drivers/gpu/drm/udl/udl_modeset.c
> +++ b/drivers/gpu/drm/udl/udl_modeset.c
> @@ -309,6 +309,8 @@ static int udl_crtc_mode_set(struct drm_crtc *crtc,
>         char *wrptr;
>         int color_depth = 0;
>
> +       udl->crtc = crtc;
> +
>         buf = (char *)udl->mode_buf;
>
>         /* for now we just clip 24 -> 16 - if we fix that fix this */
> @@ -450,6 +452,17 @@ int udl_modeset_init(struct drm_device *dev)
>         return 0;
>  }
>
> +void udl_modeset_restore(struct drm_device *dev)
> +{
> +       struct udl_device *udl = dev->dev_private;
> +       struct udl_framebuffer *ufb;
> +       if (!udl->crtc || !udl->crtc->primary->fb)
> +               return;
> +       udl_crtc_commit(udl->crtc);
> +       ufb = to_udl_fb(udl->crtc->primary->fb);
> +       udl_handle_damage(ufb, 0, 0, ufb->base.width, ufb->base.height);
> +}
> +
>  void udl_modeset_cleanup(struct drm_device *dev)
>  {
>         drm_mode_config_cleanup(dev);
> --
> 2.8.0.rc3.226.g39d4020
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
diff mbox

Patch

diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c
index 17d34e0..e5dc73b 100644
--- a/drivers/gpu/drm/udl/udl_drv.c
+++ b/drivers/gpu/drm/udl/udl_drv.c
@@ -16,6 +16,21 @@  static int udl_driver_set_busid(struct drm_device *d, struct drm_master *m)
 	return 0;
 }
 
+static int udl_usb_suspend(struct usb_interface *interface,
+			   pm_message_t message)
+{
+	return 0;
+}
+
+static int udl_usb_resume(struct usb_interface *interface)
+{
+	struct drm_device *dev = usb_get_intfdata(interface);
+
+	udl_modeset_restore(dev);
+	return 0;
+}
+
+
 static const struct vm_operations_struct udl_gem_vm_ops = {
 	.fault = udl_gem_fault,
 	.open = drm_gem_vm_open,
@@ -122,6 +137,8 @@  static struct usb_driver udl_driver = {
 	.name = "udl",
 	.probe = udl_usb_probe,
 	.disconnect = udl_usb_disconnect,
+	.suspend = udl_usb_suspend,
+	.resume = udl_usb_resume,
 	.id_table = id_table,
 };
 module_usb_driver(udl_driver);
diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h
index 0b03d34..f338a57 100644
--- a/drivers/gpu/drm/udl/udl_drv.h
+++ b/drivers/gpu/drm/udl/udl_drv.h
@@ -52,6 +52,7 @@  struct udl_device {
 	struct device *dev;
 	struct drm_device *ddev;
 	struct usb_device *udev;
+	struct drm_crtc *crtc;
 
 	int sku_pixel_limit;
 
@@ -87,6 +88,7 @@  struct udl_framebuffer {
 
 /* modeset */
 int udl_modeset_init(struct drm_device *dev);
+void udl_modeset_restore(struct drm_device *dev);
 void udl_modeset_cleanup(struct drm_device *dev);
 int udl_connector_init(struct drm_device *dev, struct drm_encoder *encoder);
 
diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c
index 7369512..69d6a4f 100644
--- a/drivers/gpu/drm/udl/udl_modeset.c
+++ b/drivers/gpu/drm/udl/udl_modeset.c
@@ -309,6 +309,8 @@  static int udl_crtc_mode_set(struct drm_crtc *crtc,
 	char *wrptr;
 	int color_depth = 0;
 
+	udl->crtc = crtc;
+
 	buf = (char *)udl->mode_buf;
 
 	/* for now we just clip 24 -> 16 - if we fix that fix this */
@@ -450,6 +452,17 @@  int udl_modeset_init(struct drm_device *dev)
 	return 0;
 }
 
+void udl_modeset_restore(struct drm_device *dev)
+{
+	struct udl_device *udl = dev->dev_private;
+	struct udl_framebuffer *ufb;
+	if (!udl->crtc || !udl->crtc->primary->fb)
+		return;
+	udl_crtc_commit(udl->crtc);
+	ufb = to_udl_fb(udl->crtc->primary->fb);
+	udl_handle_damage(ufb, 0, 0, ufb->base.width, ufb->base.height);
+}
+
 void udl_modeset_cleanup(struct drm_device *dev)
 {
 	drm_mode_config_cleanup(dev);