From 099b513168f8fd11aa838ece0769cdadb16569c6 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 17 Dec 2019 15:37:12 +0100 Subject: Add 2 patches from 5.5 to fix some nouveau issues (rhbz#1706557) --- ...-Move-the-declaration-of-struct-nouveau_c.patch | 158 +++++++++++++++++++++ ...-Fix-drm-core-using-atomic-code-paths-on-.patch | 115 +++++++++++++++ kernel.spec | 7 + 3 files changed, 280 insertions(+) create mode 100644 0001-drm-nouveau-Move-the-declaration-of-struct-nouveau_c.patch create mode 100644 0002-drm-nouveau-Fix-drm-core-using-atomic-code-paths-on-.patch diff --git a/0001-drm-nouveau-Move-the-declaration-of-struct-nouveau_c.patch b/0001-drm-nouveau-Move-the-declaration-of-struct-nouveau_c.patch new file mode 100644 index 000000000..548304eab --- /dev/null +++ b/0001-drm-nouveau-Move-the-declaration-of-struct-nouveau_c.patch @@ -0,0 +1,158 @@ +From 37a68eab4cd92b507c9e8afd760fdc18e4fecac6 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Thu, 24 Oct 2019 10:52:52 +0200 +Subject: [PATCH v2 1/2] drm/nouveau: Move the declaration of struct + nouveau_conn_atom up a bit + +Place the declaration of struct nouveau_conn_atom above that of +struct nouveau_connector. This commit makes no changes to the moved +block what so ever, it just moves it up a bit. + +This is a preparation patch to fix some issues with connector handling +on pre nv50 displays (which do not use atomic modesetting). + +Signed-off-by: Hans de Goede +Reviewed-by: Lyude Paul +Signed-off-by: Ben Skeggs +--- + drivers/gpu/drm/nouveau/nouveau_connector.h | 110 ++++++++++---------- + 1 file changed, 55 insertions(+), 55 deletions(-) + +diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h +index f43a8d63aef8..de9588420884 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_connector.h ++++ b/drivers/gpu/drm/nouveau/nouveau_connector.h +@@ -29,6 +29,7 @@ + + #include + ++#include + #include + #include + #include +@@ -44,6 +45,60 @@ struct dcb_output; + struct nouveau_backlight; + #endif + ++#define nouveau_conn_atom(p) \ ++ container_of((p), struct nouveau_conn_atom, state) ++ ++struct nouveau_conn_atom { ++ struct drm_connector_state state; ++ ++ struct { ++ /* The enum values specifically defined here match nv50/gf119 ++ * hw values, and the code relies on this. ++ */ ++ enum { ++ DITHERING_MODE_OFF = 0x00, ++ DITHERING_MODE_ON = 0x01, ++ DITHERING_MODE_DYNAMIC2X2 = 0x10 | DITHERING_MODE_ON, ++ DITHERING_MODE_STATIC2X2 = 0x18 | DITHERING_MODE_ON, ++ DITHERING_MODE_TEMPORAL = 0x20 | DITHERING_MODE_ON, ++ DITHERING_MODE_AUTO ++ } mode; ++ enum { ++ DITHERING_DEPTH_6BPC = 0x00, ++ DITHERING_DEPTH_8BPC = 0x02, ++ DITHERING_DEPTH_AUTO ++ } depth; ++ } dither; ++ ++ struct { ++ int mode; /* DRM_MODE_SCALE_* */ ++ struct { ++ enum { ++ UNDERSCAN_OFF, ++ UNDERSCAN_ON, ++ UNDERSCAN_AUTO, ++ } mode; ++ u32 hborder; ++ u32 vborder; ++ } underscan; ++ bool full; ++ } scaler; ++ ++ struct { ++ int color_vibrance; ++ int vibrant_hue; ++ } procamp; ++ ++ union { ++ struct { ++ bool dither:1; ++ bool scaler:1; ++ bool procamp:1; ++ }; ++ u8 mask; ++ } set; ++}; ++ + struct nouveau_connector { + struct drm_connector base; + enum dcb_connector_type type; +@@ -121,61 +176,6 @@ extern int nouveau_ignorelid; + extern int nouveau_duallink; + extern int nouveau_hdmimhz; + +-#include +-#define nouveau_conn_atom(p) \ +- container_of((p), struct nouveau_conn_atom, state) +- +-struct nouveau_conn_atom { +- struct drm_connector_state state; +- +- struct { +- /* The enum values specifically defined here match nv50/gf119 +- * hw values, and the code relies on this. +- */ +- enum { +- DITHERING_MODE_OFF = 0x00, +- DITHERING_MODE_ON = 0x01, +- DITHERING_MODE_DYNAMIC2X2 = 0x10 | DITHERING_MODE_ON, +- DITHERING_MODE_STATIC2X2 = 0x18 | DITHERING_MODE_ON, +- DITHERING_MODE_TEMPORAL = 0x20 | DITHERING_MODE_ON, +- DITHERING_MODE_AUTO +- } mode; +- enum { +- DITHERING_DEPTH_6BPC = 0x00, +- DITHERING_DEPTH_8BPC = 0x02, +- DITHERING_DEPTH_AUTO +- } depth; +- } dither; +- +- struct { +- int mode; /* DRM_MODE_SCALE_* */ +- struct { +- enum { +- UNDERSCAN_OFF, +- UNDERSCAN_ON, +- UNDERSCAN_AUTO, +- } mode; +- u32 hborder; +- u32 vborder; +- } underscan; +- bool full; +- } scaler; +- +- struct { +- int color_vibrance; +- int vibrant_hue; +- } procamp; +- +- union { +- struct { +- bool dither:1; +- bool scaler:1; +- bool procamp:1; +- }; +- u8 mask; +- } set; +-}; +- + void nouveau_conn_attach_properties(struct drm_connector *); + void nouveau_conn_reset(struct drm_connector *); + struct drm_connector_state * +-- +2.23.0 + diff --git a/0002-drm-nouveau-Fix-drm-core-using-atomic-code-paths-on-.patch b/0002-drm-nouveau-Fix-drm-core-using-atomic-code-paths-on-.patch new file mode 100644 index 000000000..077f391ca --- /dev/null +++ b/0002-drm-nouveau-Fix-drm-core-using-atomic-code-paths-on-.patch @@ -0,0 +1,115 @@ +From 64d17f25dcad518461ccf0c260544e1e379c5b35 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Thu, 24 Oct 2019 10:52:53 +0200 +Subject: [PATCH v2 2/2] drm/nouveau: Fix drm-core using atomic code-paths on + pre-nv50 hardware + +We do not support atomic modesetting on pre-nv50 hardware, but until now +our connector code was setting drm_connector->state on pre-nv50 hardware. + +This causes the core to enter atomic modesetting paths in at least: + +1. drm_connector_get_encoder(), returning connector->state->best_encoder +which is always 0, causing us to always report 0 as encoder_id in +the drmModeConnector struct returned by drmModeGetConnector(). + +2. drm_encoder_get_crtc(), returning NULL because uses_atomic get set, +causing us to always report 0 as crtc_id in the drmModeEncoder struct +returned by drmModeGetEncoder() + +Which in turn confuses userspace, at least plymouth thinks that the pipe +has changed because of this and tries to reconfigure it unnecessarily. + +More in general we should not set drm_connector->state in the non-atomic +code as this violates the drm-core's expectations. + +This commit fixes this by using a nouveau_conn_atom struct embedded in the +nouveau_connector struct for property handling in the non-atomic case. + +Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1706557 +Signed-off-by: Hans de Goede +Signed-off-by: Ben Skeggs +--- + drivers/gpu/drm/nouveau/nouveau_connector.c | 28 +++++++++++++++------ + drivers/gpu/drm/nouveau/nouveau_connector.h | 6 +++++ + 2 files changed, 27 insertions(+), 7 deletions(-) + +diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c +index 5b413588b823..9a9a7f5003d3 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_connector.c ++++ b/drivers/gpu/drm/nouveau/nouveau_connector.c +@@ -245,14 +245,22 @@ nouveau_conn_atomic_duplicate_state(struct drm_connector *connector) + void + nouveau_conn_reset(struct drm_connector *connector) + { ++ struct nouveau_connector *nv_connector = nouveau_connector(connector); + struct nouveau_conn_atom *asyc; + +- if (WARN_ON(!(asyc = kzalloc(sizeof(*asyc), GFP_KERNEL)))) +- return; ++ if (drm_drv_uses_atomic_modeset(connector->dev)) { ++ if (WARN_ON(!(asyc = kzalloc(sizeof(*asyc), GFP_KERNEL)))) ++ return; ++ ++ if (connector->state) ++ nouveau_conn_atomic_destroy_state(connector, ++ connector->state); ++ ++ __drm_atomic_helper_connector_reset(connector, &asyc->state); ++ } else { ++ asyc = &nv_connector->properties_state; ++ } + +- if (connector->state) +- nouveau_conn_atomic_destroy_state(connector, connector->state); +- __drm_atomic_helper_connector_reset(connector, &asyc->state); + asyc->dither.mode = DITHERING_MODE_AUTO; + asyc->dither.depth = DITHERING_DEPTH_AUTO; + asyc->scaler.mode = DRM_MODE_SCALE_NONE; +@@ -276,8 +284,14 @@ void + nouveau_conn_attach_properties(struct drm_connector *connector) + { + struct drm_device *dev = connector->dev; +- struct nouveau_conn_atom *armc = nouveau_conn_atom(connector->state); + struct nouveau_display *disp = nouveau_display(dev); ++ struct nouveau_connector *nv_connector = nouveau_connector(connector); ++ struct nouveau_conn_atom *armc; ++ ++ if (drm_drv_uses_atomic_modeset(connector->dev)) ++ armc = nouveau_conn_atom(connector->state); ++ else ++ armc = &nv_connector->properties_state; + + /* Init DVI-I specific properties. */ + if (connector->connector_type == DRM_MODE_CONNECTOR_DVII) +@@ -748,9 +762,9 @@ static int + nouveau_connector_set_property(struct drm_connector *connector, + struct drm_property *property, uint64_t value) + { +- struct nouveau_conn_atom *asyc = nouveau_conn_atom(connector->state); + struct nouveau_connector *nv_connector = nouveau_connector(connector); + struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; ++ struct nouveau_conn_atom *asyc = &nv_connector->properties_state; + struct drm_encoder *encoder = to_drm_encoder(nv_encoder); + int ret; + +diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h +index de9588420884..de84fb4708c7 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_connector.h ++++ b/drivers/gpu/drm/nouveau/nouveau_connector.h +@@ -118,6 +118,12 @@ struct nouveau_connector { + #ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT + struct nouveau_backlight *backlight; + #endif ++ /* ++ * Our connector property code expects a nouveau_conn_atom struct ++ * even on pre-nv50 where we do not support atomic. This embedded ++ * version gets used in the non atomic modeset case. ++ */ ++ struct nouveau_conn_atom properties_state; + }; + + static inline struct nouveau_connector *nouveau_connector( +-- +2.23.0 + diff --git a/kernel.spec b/kernel.spec index 927011d58..e7bcb0ff2 100644 --- a/kernel.spec +++ b/kernel.spec @@ -865,6 +865,10 @@ Patch600: alsa-5.5.patch # ALSA code from v5.6 (Intel ASoC Sound Open Firmware driver support) Patch607: alsa-5.6.patch +# rhbz 1706557, both patches are upstream in v5.5-rc2 +Patch608: 0001-drm-nouveau-Move-the-declaration-of-struct-nouveau_c.patch +Patch609: 0002-drm-nouveau-Fix-drm-core-using-atomic-code-paths-on-.patch + # END OF PATCH DEFINITIONS %endif @@ -2566,6 +2570,9 @@ fi # # %changelog +* Tue Dec 17 2019 Hans de Goede +- Add 2 patches from 5.5 to fix some nouveau issues (rhbz#1706557) + * Fri Dec 13 2019 Jeremy Cline - 5.4.3-300 - Linux v5.4.3 -- cgit