Skip to content

Commit faa0fcf

Browse files
cubanismoairlied
authored andcommitted
drm/nouveau: Accept 'legacy' format modifiers
Accept the DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK() family of modifiers to handle broken userspace Xorg modesetting and Mesa drivers. Existing Mesa drivers are still aware of only these older format modifiers which do not differentiate between different variations of the block linear layout. When the format modifier support flag was flipped in the nouveau kernel driver, the X.org modesetting driver began attempting to use its format modifier-enabled framebuffer path. Because the set of format modifiers advertised by the kernel prior to this change do not intersect with the set of format modifiers advertised by Mesa, allocating GBM buffers using format modifiers fails and the modesetting driver falls back to non-modifier allocation. However, it still later queries the modifier of the GBM buffer when creating its DRM-KMS framebuffer object, receives the old-format modifier from Mesa, and attempts to create a framebuffer with it. Since the kernel is still not aware of these formats, this fails. Userspace should not be attempting to query format modifiers of GBM buffers allocated with a non- format-modifier-aware allocation path, but to avoid breaking existing userspace behavior, this change accepts the old-style format modifiers when creating framebuffers and applying them to planes by translating them to the equivalent new-style modifier. To accomplish this, some layout parameters must be assumed to match properties of the device targeted by the relevant ioctls. To avoid perpetuating misuse of the old-style modifiers, this change does not advertise support for them. Doing so would imply compatibility between devices with incompatible memory layouts. Tested with Xorg 1.20 modesetting driver, weston@c46c70dac84a4b3030cd05b380f9f410536690fc, gnome & KDE wayland desktops from Ubuntu 18.04, and sway 1.5 Reported-by: Kirill A. Shutemov <[email protected]> Fixes: fa4f4c2 ("drm/nouveau/kms: Support NVIDIA format modifiers") Link: https://lkml.org/lkml/2020/6/30/1251 Signed-off-by: James Jones <[email protected]> Acked-by: Ben Skeggs <[email protected]> Signed-off-by: Dave Airlie <[email protected]>
1 parent a4a2739 commit faa0fcf

File tree

1 file changed

+25
-2
lines changed

1 file changed

+25
-2
lines changed

drivers/gpu/drm/nouveau/nouveau_display.c

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ nouveau_decode_mod(struct nouveau_drm *drm,
191191
uint32_t *tile_mode,
192192
uint8_t *kind)
193193
{
194+
struct nouveau_display *disp = nouveau_display(drm->dev);
194195
BUG_ON(!tile_mode || !kind);
195196

196197
if (modifier == DRM_FORMAT_MOD_LINEAR) {
@@ -202,6 +203,12 @@ nouveau_decode_mod(struct nouveau_drm *drm,
202203
* Extract the block height and kind from the corresponding
203204
* modifier fields. See drm_fourcc.h for details.
204205
*/
206+
207+
if ((modifier & (0xffull << 12)) == 0ull) {
208+
/* Legacy modifier. Translate to this dev's 'kind.' */
209+
modifier |= disp->format_modifiers[0] & (0xffull << 12);
210+
}
211+
205212
*tile_mode = (uint32_t)(modifier & 0xF);
206213
*kind = (uint8_t)((modifier >> 12) & 0xFF);
207214

@@ -227,6 +234,16 @@ nouveau_framebuffer_get_layout(struct drm_framebuffer *fb,
227234
}
228235
}
229236

237+
static const u64 legacy_modifiers[] = {
238+
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(0),
239+
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(1),
240+
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(2),
241+
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(3),
242+
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(4),
243+
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(5),
244+
DRM_FORMAT_MOD_INVALID
245+
};
246+
230247
static int
231248
nouveau_validate_decode_mod(struct nouveau_drm *drm,
232249
uint64_t modifier,
@@ -247,8 +264,14 @@ nouveau_validate_decode_mod(struct nouveau_drm *drm,
247264
(disp->format_modifiers[mod] != modifier);
248265
mod++);
249266

250-
if (disp->format_modifiers[mod] == DRM_FORMAT_MOD_INVALID)
251-
return -EINVAL;
267+
if (disp->format_modifiers[mod] == DRM_FORMAT_MOD_INVALID) {
268+
for (mod = 0;
269+
(legacy_modifiers[mod] != DRM_FORMAT_MOD_INVALID) &&
270+
(legacy_modifiers[mod] != modifier);
271+
mod++);
272+
if (legacy_modifiers[mod] == DRM_FORMAT_MOD_INVALID)
273+
return -EINVAL;
274+
}
252275

253276
nouveau_decode_mod(drm, modifier, tile_mode, kind);
254277

0 commit comments

Comments
 (0)