From 55f556b1082610ac248b1509dcc03f3a29e8b1eb Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 8 Jan 2013 03:25:52 +0000 Subject: [PATCH] radeon, amdgpu: Firmware is required for DRM and KMS on R600 onward Bug-Debian: https://bugs.debian.org/607194 Bug-Debian: https://bugs.debian.org/607471 Bug-Debian: https://bugs.debian.org/610851 Bug-Debian: https://bugs.debian.org/627497 Bug-Debian: https://bugs.debian.org/632212 Bug-Debian: https://bugs.debian.org/637943 Bug-Debian: https://bugs.debian.org/649448 Bug-Debian: https://bugs.debian.org/697229 Forwarded: no radeon requires firmware/microcode for the GPU in 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. Therefore, perform a basic check for the existence of /lib/firmware/{radeon,amdgpu} when a device is probed, and abort if it is missing, except for the pre-R600 case. Gbp-Pq: Topic bugfix/all Gbp-Pq: Name radeon-amdgpu-firmware-is-required-for-drm-and-kms-on-r600-onward.patch --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 29 ++++++++++++++++++++++++ drivers/gpu/drm/radeon/radeon_drv.c | 30 +++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index de7144b06e9..137244029e2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -38,6 +38,8 @@ #include #include #include +#include +#include #include "amdgpu.h" #include "amdgpu_irq.h" @@ -1998,6 +2000,28 @@ static void amdgpu_get_secondary_funcs(struct amdgpu_device *adev) } } +/* Test that /lib/firmware/amdgpu is a directory (or symlink to a + * directory). We could try to match the udev search path, but let's + * keep it simple. + */ +static bool amdgpu_firmware_installed(void) +{ +#if IS_BUILTIN(CONFIG_DRM_AMDGPU) + /* It may be too early to tell. Assume it's there. */ + return true; +#else + struct path path; + + if (kern_path("/lib/firmware/amdgpu", LOOKUP_DIRECTORY | LOOKUP_FOLLOW, + &path) == 0) { + path_put(&path); + return true; + } + + return false; +#endif +} + static int amdgpu_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -2072,6 +2096,11 @@ static int amdgpu_pci_probe(struct pci_dev *pdev, } #endif + if (!amdgpu_firmware_installed()) { + DRM_ERROR("amdgpu requires firmware installed\n"); + return -ENODEV; + } + /* Get rid of things like offb */ ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, &amdgpu_kms_driver); if (ret) diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 956c72b5aa3..a9ba3782511 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -48,6 +48,8 @@ #include #include #include +#include +#include #include "radeon_drv.h" #include "radeon.h" @@ -288,6 +290,28 @@ MODULE_DEVICE_TABLE(pci, pciidlist); static const struct drm_driver kms_driver; +/* 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 + * keep it simple. + */ +static bool radeon_firmware_installed(void) +{ +#if IS_BUILTIN(CONFIG_DRM_RADEON) + /* It may be too early to tell. Assume it's there. */ + return true; +#else + struct path path; + + if (kern_path("/lib/firmware/radeon", LOOKUP_DIRECTORY | LOOKUP_FOLLOW, + &path) == 0) { + path_put(&path); + return true; + } + + return false; +#endif +} + static int radeon_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -328,6 +352,12 @@ static int radeon_pci_probe(struct pci_dev *pdev, if (vga_switcheroo_client_probe_defer(pdev)) return -EPROBE_DEFER; + if ((ent->driver_data & RADEON_FAMILY_MASK) >= CHIP_R600 && + !radeon_firmware_installed()) { + DRM_ERROR("radeon kernel modesetting for R600 or later requires firmware installed\n"); + return -ENODEV; + } + /* Get rid of things like offb */ ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, &kms_driver); if (ret) -- 2.30.2