| From ba951529973e0c617b6522230ed88b42a8c3dacb Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Tue, 4 Sep 2018 22:27:47 +0200 |
| Subject: qxl: fix null-pointer crash during suspend |
| |
| From: Peter Wu <peter@lekensteyn.nl> |
| |
| [ Upstream commit 7948a2b15873319d1bff4d37c09b9f2bf87b9021 ] |
| |
| "crtc->helper_private" is not initialized by the QXL driver and thus the |
| "crtc_funcs->disable" call would crash (resulting in suspend failure). |
| Fix this by converting the suspend/resume functions to use the |
| drm_mode_config_helper_* helpers. |
| |
| Tested system sleep with QEMU 3.0 using "echo mem > /sys/power/state". |
| During suspend the following message is visible from QEMU: |
| |
| spice/server/display-channel.c:2425:display_channel_validate_surface: canvas address is 0x7fd05da68308 for 0 (and is NULL) |
| spice/server/display-channel.c:2426:display_channel_validate_surface: failed on 0 |
| |
| This seems to be triggered by QXL_IO_NOTIFY_CMD after |
| QXL_IO_DESTROY_PRIMARY_ASYNC, but aside from the warning things still |
| seem to work (tested with both the GTK and -spice options). |
| |
| Signed-off-by: Peter Wu <peter@lekensteyn.nl> |
| Link: http://patchwork.freedesktop.org/patch/msgid/20180904202747.14968-1-peter@lekensteyn.nl |
| Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/gpu/drm/qxl/qxl_drv.c | 26 +++++--------------------- |
| 1 file changed, 5 insertions(+), 21 deletions(-) |
| |
| diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c |
| index 2445e75cf7ea6..d00f45eed03ca 100644 |
| --- a/drivers/gpu/drm/qxl/qxl_drv.c |
| +++ b/drivers/gpu/drm/qxl/qxl_drv.c |
| @@ -136,20 +136,11 @@ static int qxl_drm_freeze(struct drm_device *dev) |
| { |
| struct pci_dev *pdev = dev->pdev; |
| struct qxl_device *qdev = dev->dev_private; |
| - struct drm_crtc *crtc; |
| - |
| - drm_kms_helper_poll_disable(dev); |
| - |
| - console_lock(); |
| - qxl_fbdev_set_suspend(qdev, 1); |
| - console_unlock(); |
| + int ret; |
| |
| - /* unpin the front buffers */ |
| - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
| - const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; |
| - if (crtc->enabled) |
| - (*crtc_funcs->disable)(crtc); |
| - } |
| + ret = drm_mode_config_helper_suspend(dev); |
| + if (ret) |
| + return ret; |
| |
| qxl_destroy_monitors_object(qdev); |
| qxl_surf_evict(qdev); |
| @@ -175,14 +166,7 @@ static int qxl_drm_resume(struct drm_device *dev, bool thaw) |
| } |
| |
| qxl_create_monitors_object(qdev); |
| - drm_helper_resume_force_mode(dev); |
| - |
| - console_lock(); |
| - qxl_fbdev_set_suspend(qdev, 0); |
| - console_unlock(); |
| - |
| - drm_kms_helper_poll_enable(dev); |
| - return 0; |
| + return drm_mode_config_helper_resume(dev); |
| } |
| |
| static int qxl_pm_suspend(struct device *dev) |
| -- |
| 2.20.1 |
| |