From: Ben Hutchings Subject: radeon: No MODESET without firmware Date: Sat, 17 Nov 2012 05:28:53 +0000 Bug-Debian: http://bugs.debian.org/607194 Bug-Debian: http://bugs.debian.org/607471 Bug-Debian: http://bugs.debian.org/610851 Bug-Debian: http://bugs.debian.org/627497 Bug-Debian: http://bugs.debian.org/632212 Bug-Debian: http://bugs.debian.org/637943 Bug-Debian: http://bugs.debian.org/649448 radeon requires firmware/microcode for the GPU all chips, but for newer chips (apparently R600 'Evergreen' onward) it also expects firmware for the memory controller and other sub-blocks. radeon attempts to gracefully fall back and disable some features if the firmware is not available, but becomes unstable - the framebuffer and/or system memory may be corrupted, or the display may stay black. This does not seem to happen if KMS is disabled. Unfortunately, it is not possible to properly disable KMS once the missing firmware is discovered. Each driver registers with the DRM core as having certain capabilities such as DRIVER_MODESET (KMS) and the DRM does not allow for individual devices to have different capabilities! Therefore, perform a basic check for the existence of /lib/firmware/radeon when the driver is loaded, and disable KMS if it is missing. I apologise for this gross hack, but I cannot see any more reliable solution that doesn't involve major changes to both DRM and radeon. --- --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -36,6 +36,8 @@ #include #include #include +#include +#include /* @@ -411,6 +413,24 @@ static struct pci_driver radeon_kms_pci_ .resume = radeon_pci_resume, }; +/* Test that /lib/firmware/radeon is a directory (or symlink to a + * directory). We could try to match the udev search path, but let's + * assume people take the easy route and install + * firmware-linux-nonfree. + */ +static bool __init radeon_firmware_installed(void) +{ + struct path path; + + if (kern_path("/lib/firmware/radeon", LOOKUP_DIRECTORY | LOOKUP_FOLLOW, + &path) == 0) { + path_put(&path); + return true; + } + + return false; +} + static int __init radeon_init(void) { driver = &driver_old; @@ -435,6 +455,13 @@ static int __init radeon_init(void) radeon_modeset = 0; #endif } + /* We have to commit to KMS before we've seen any devices, so + * make a basic check to reduce the risk of failure later. + */ + if (radeon_modeset == 1 && !radeon_firmware_installed()) { + DRM_INFO("radeon kernel modesetting disabled; it requires firmware-linux-nonfree.\n"); + radeon_modeset = 0; + } if (radeon_modeset == 1) { DRM_INFO("radeon kernel modesetting enabled.\n"); driver = &kms_driver;