[kernel/f19] Add qxl backport fixes from Dave Airlie

Josh Boyer jwboyer at fedoraproject.org
Sat Nov 9 15:13:49 UTC 2013


commit a8d117eaca98cd2046485d7225162f5d7943434c
Author: Josh Boyer <jwboyer at fedoraproject.org>
Date:   Sat Nov 9 09:30:06 2013 -0500

    Add qxl backport fixes from Dave Airlie

 drm-qxl-backport-fixes-for-Fedora.patch |  226 +++++++++++++++++++++++++++++++
 kernel.spec                             |    7 +
 2 files changed, 233 insertions(+), 0 deletions(-)
---
diff --git a/drm-qxl-backport-fixes-for-Fedora.patch b/drm-qxl-backport-fixes-for-Fedora.patch
new file mode 100644
index 0000000..c46060d
--- /dev/null
+++ b/drm-qxl-backport-fixes-for-Fedora.patch
@@ -0,0 +1,226 @@
+Bugzilla: N/A
+Upstream-status: Queued for 3.13
+
+From db8edc33193879f39c1b52521e20f4d6eb4e9858 Mon Sep 17 00:00:00 2001
+From: Dave Airlie <airlied at redhat.com>
+Date: Fri, 08 Nov 2013 06:36:45 +0000
+Subject: drm/qxl: backport fixes for Fedora
+
+This pulls these changes from drm-next back into Fedora.
+
+drm/qxl: prefer the monitor config resolution (b080742393e2c1)
+drm/qxl: remove unnecessary check (a40a60d912a101e8dfb08ee1)
+drm/qxl: fix disabling extra monitors from client (5cab51cb3381157)
+qxl: avoid an oops in the deferred io code. (cc87509d87696d7cd39)
+drm/qxl: support 64bit surface bar (35541782dcc1e502)
+qxl: add a connector property to denote hotplug should rescan modes. (4695b03970df37)
+
+Signed-off-by: Dave Airlie <airlied at redhat.com>
+---
+diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
+index 835caba..1d975eb 100644
+--- a/drivers/gpu/drm/qxl/qxl_display.c
++++ b/drivers/gpu/drm/qxl/qxl_display.c
+@@ -110,7 +110,9 @@ void qxl_display_read_client_monitors_config(struct qxl_device *qdev)
+ 	drm_helper_hpd_irq_event(qdev->ddev);
+ }
+ 
+-static int qxl_add_monitors_config_modes(struct drm_connector *connector)
++static int qxl_add_monitors_config_modes(struct drm_connector *connector,
++                                         unsigned *pwidth,
++                                         unsigned *pheight)
+ {
+ 	struct drm_device *dev = connector->dev;
+ 	struct qxl_device *qdev = dev->dev_private;
+@@ -126,11 +128,15 @@ static int qxl_add_monitors_config_modes(struct drm_connector *connector)
+ 	mode = drm_cvt_mode(dev, head->width, head->height, 60, false, false,
+ 			    false);
+ 	mode->type |= DRM_MODE_TYPE_PREFERRED;
++	*pwidth = head->width;
++	*pheight = head->height;
+ 	drm_mode_probed_add(connector, mode);
+ 	return 1;
+ }
+ 
+-static int qxl_add_common_modes(struct drm_connector *connector)
++static int qxl_add_common_modes(struct drm_connector *connector,
++                                unsigned pwidth,
++                                unsigned pheight)
+ {
+ 	struct drm_device *dev = connector->dev;
+ 	struct drm_display_mode *mode = NULL;
+@@ -159,12 +165,9 @@ static int qxl_add_common_modes(struct drm_connector *connector)
+ 	};
+ 
+ 	for (i = 0; i < ARRAY_SIZE(common_modes); i++) {
+-		if (common_modes[i].w < 320 || common_modes[i].h < 200)
+-			continue;
+-
+ 		mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h,
+ 				    60, false, false, false);
+-		if (common_modes[i].w == 1024 && common_modes[i].h == 768)
++		if (common_modes[i].w == pwidth && common_modes[i].h == pheight)
+ 			mode->type |= DRM_MODE_TYPE_PREFERRED;
+ 		drm_mode_probed_add(connector, mode);
+ 	}
+@@ -720,16 +723,18 @@ static int qxl_conn_get_modes(struct drm_connector *connector)
+ {
+ 	int ret = 0;
+ 	struct qxl_device *qdev = connector->dev->dev_private;
++	unsigned pwidth = 1024;
++	unsigned pheight = 768;
+ 
+ 	DRM_DEBUG_KMS("monitors_config=%p\n", qdev->monitors_config);
+ 	/* TODO: what should we do here? only show the configured modes for the
+ 	 * device, or allow the full list, or both? */
+ 	if (qdev->monitors_config && qdev->monitors_config->count) {
+-		ret = qxl_add_monitors_config_modes(connector);
++		ret = qxl_add_monitors_config_modes(connector, &pwidth, &pheight);
+ 		if (ret < 0)
+ 			return ret;
+ 	}
+-	ret += qxl_add_common_modes(connector);
++	ret += qxl_add_common_modes(connector, pwidth, pheight);
+ 	return ret;
+ }
+ 
+@@ -793,7 +798,10 @@ static enum drm_connector_status qxl_conn_detect(
+ 		     qdev->client_monitors_config->count > output->index &&
+ 		     qxl_head_enabled(&qdev->client_monitors_config->heads[output->index]));
+ 
+-	DRM_DEBUG("\n");
++	DRM_DEBUG("#%d connected: %d\n", output->index, connected);
++	if (!connected)
++		qxl_monitors_config_set(qdev, output->index, 0, 0, 0, 0, 0);
++
+ 	return connected ? connector_status_connected
+ 			 : connector_status_disconnected;
+ }
+@@ -835,8 +843,21 @@ static const struct drm_encoder_funcs qxl_enc_funcs = {
+ 	.destroy = qxl_enc_destroy,
+ };
+ 
++static int qxl_mode_create_hotplug_mode_update_property(struct qxl_device *qdev)
++{
++	if (qdev->hotplug_mode_update_property)
++		return 0;
++
++	qdev->hotplug_mode_update_property =
++		drm_property_create_range(qdev->ddev, DRM_MODE_PROP_IMMUTABLE,
++					  "hotplug_mode_update", 0, 1);
++
++	return 0;
++}
++
+ static int qdev_output_init(struct drm_device *dev, int num_output)
+ {
++	struct qxl_device *qdev = dev->dev_private;
+ 	struct qxl_output *qxl_output;
+ 	struct drm_connector *connector;
+ 	struct drm_encoder *encoder;
+@@ -863,6 +884,8 @@ static int qdev_output_init(struct drm_device *dev, int num_output)
+ 	drm_encoder_helper_add(encoder, &qxl_enc_helper_funcs);
+ 	drm_connector_helper_add(connector, &qxl_connector_helper_funcs);
+ 
++	drm_object_attach_property(&connector->base,
++				   qdev->hotplug_mode_update_property, 0);
+ 	drm_sysfs_connector_add(connector);
+ 	return 0;
+ }
+@@ -975,6 +998,9 @@ int qxl_modeset_init(struct qxl_device *qdev)
+ 	qdev->ddev->mode_config.max_height = 8192;
+ 
+ 	qdev->ddev->mode_config.fb_base = qdev->vram_base;
++
++	qxl_mode_create_hotplug_mode_update_property(qdev);
++
+ 	for (i = 0 ; i < qxl_num_crtc; ++i) {
+ 		qdev_crtc_init(qdev->ddev, i);
+ 		qdev_output_init(qdev->ddev, i);
+diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
+index 7e96f4f..18c599d 100644
+--- a/drivers/gpu/drm/qxl/qxl_drv.h
++++ b/drivers/gpu/drm/qxl/qxl_drv.h
+@@ -323,6 +323,8 @@ struct qxl_device {
+ 	struct work_struct gc_work;
+ 
+ 	struct work_struct fb_work;
++
++	struct drm_property *hotplug_mode_update_property;
+ };
+ 
+ /* forward declaration for QXL_INFO_IO */
+diff --git a/drivers/gpu/drm/qxl/qxl_fb.c b/drivers/gpu/drm/qxl/qxl_fb.c
+index 88722f2..f437b30 100644
+--- a/drivers/gpu/drm/qxl/qxl_fb.c
++++ b/drivers/gpu/drm/qxl/qxl_fb.c
+@@ -108,7 +108,7 @@ static void qxl_fb_dirty_flush(struct fb_info *info)
+ 	u32 x1, x2, y1, y2;
+ 
+ 	/* TODO: hard coding 32 bpp */
+-	int stride = qfbdev->qfb.base.pitches[0] * 4;
++	int stride = qfbdev->qfb.base.pitches[0];
+ 
+ 	x1 = qfbdev->dirty.x1;
+ 	x2 = qfbdev->dirty.x2;
+diff --git a/drivers/gpu/drm/qxl/qxl_kms.c b/drivers/gpu/drm/qxl/qxl_kms.c
+index 9e8da9e..e0ddd5b 100644
+--- a/drivers/gpu/drm/qxl/qxl_kms.c
++++ b/drivers/gpu/drm/qxl/qxl_kms.c
+@@ -120,7 +120,7 @@ int qxl_device_init(struct qxl_device *qdev,
+ 		    struct pci_dev *pdev,
+ 		    unsigned long flags)
+ {
+-	int r;
++	int r, sb;
+ 
+ 	qdev->dev = &pdev->dev;
+ 	qdev->ddev = ddev;
+@@ -136,21 +136,39 @@ int qxl_device_init(struct qxl_device *qdev,
+ 	qdev->rom_base = pci_resource_start(pdev, 2);
+ 	qdev->rom_size = pci_resource_len(pdev, 2);
+ 	qdev->vram_base = pci_resource_start(pdev, 0);
+-	qdev->surfaceram_base = pci_resource_start(pdev, 1);
+-	qdev->surfaceram_size = pci_resource_len(pdev, 1);
+ 	qdev->io_base = pci_resource_start(pdev, 3);
+ 
+ 	qdev->vram_mapping = io_mapping_create_wc(qdev->vram_base, pci_resource_len(pdev, 0));
+-	qdev->surface_mapping = io_mapping_create_wc(qdev->surfaceram_base, qdev->surfaceram_size);
+-	DRM_DEBUG_KMS("qxl: vram %llx-%llx(%dM %dk), surface %llx-%llx(%dM %dk)\n",
++
++	if (pci_resource_len(pdev, 4) > 0) {
++		/* 64bit surface bar present */
++		sb = 4;
++		qdev->surfaceram_base = pci_resource_start(pdev, sb);
++		qdev->surfaceram_size = pci_resource_len(pdev, sb);
++		qdev->surface_mapping =
++			io_mapping_create_wc(qdev->surfaceram_base,
++					     qdev->surfaceram_size);
++	}
++	if (qdev->surface_mapping == NULL) {
++		/* 64bit surface bar not present (or mapping failed) */
++		sb = 1;
++		qdev->surfaceram_base = pci_resource_start(pdev, sb);
++		qdev->surfaceram_size = pci_resource_len(pdev, sb);
++		qdev->surface_mapping =
++			io_mapping_create_wc(qdev->surfaceram_base,
++					     qdev->surfaceram_size);
++	}
++
++	DRM_DEBUG_KMS("qxl: vram %llx-%llx(%dM %dk), surface %llx-%llx(%dM %dk, %s)\n",
+ 		 (unsigned long long)qdev->vram_base,
+ 		 (unsigned long long)pci_resource_end(pdev, 0),
+ 		 (int)pci_resource_len(pdev, 0) / 1024 / 1024,
+ 		 (int)pci_resource_len(pdev, 0) / 1024,
+ 		 (unsigned long long)qdev->surfaceram_base,
+-		 (unsigned long long)pci_resource_end(pdev, 1),
++		 (unsigned long long)pci_resource_end(pdev, sb),
+ 		 (int)qdev->surfaceram_size / 1024 / 1024,
+-		 (int)qdev->surfaceram_size / 1024);
++		 (int)qdev->surfaceram_size / 1024,
++		 (sb == 4) ? "64bit" : "32bit");
+ 
+ 	qdev->rom = ioremap(qdev->rom_base, qdev->rom_size);
+ 	if (!qdev->rom) {
+--
+cgit v0.9.0.2-2-gbebe
diff --git a/kernel.spec b/kernel.spec
index 48670f3..4a01de3 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -795,6 +795,8 @@ Patch25141: 0001-Revert-select-use-freezable-blocking-call.patch
 #rhbz 1025769
 Patch25142: iwlwifi-dvm-dont-override-mac80211-queue-setting.patch
 
+Patch25143: drm-qxl-backport-fixes-for-Fedora.patch
+
 # END OF PATCH DEFINITIONS
 
 %endif
@@ -1538,6 +1540,8 @@ ApplyPatch 0001-Revert-select-use-freezable-blocking-call.patch
 #rhbz 1025769
 ApplyPatch iwlwifi-dvm-dont-override-mac80211-queue-setting.patch
 
+ApplyPatch drm-qxl-backport-fixes-for-Fedora.patch
+
 # END OF PATCH APPLICATIONS
 
 %endif
@@ -2350,6 +2354,9 @@ fi
 # and build.
 
 %changelog
+* Sat Nov 09 2013 Josh Boyer <jwboyer at fedoraproject.org>
+- Add qxl backport fixes from Dave Airlie
+
 * Mon Nov 04 2013 Josh Boyer <jwboyer at fedoraproject.org> - 3.11.7-200
 - Add patch to fix iwlwifi queue settings backtrace (rhbz 1025769)
 


More information about the scm-commits mailing list