Message ID | 1472593821-38429-2-git-send-email-hshi@chromium.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
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 --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);