Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/radeon: Return -EPROBE_DEFER when amdkfd not loaded

radeon must load only after amdkfd's loading has been completed. If that
is not enforced, then radeon's call into amdkfd's functions will cause a
kernel BUG.

When radeon and amdkfd are built as kernel modules, that rule is
enforced by the kernel's modules loading mechanism. When radeon and
amdkfd are built inside the kernel image, that rule is enforced by
ordering in the drm Makefile (amdkfd before radeon).

Instead of using drm Makefile ordering, we can now use deferred
loading as amdkfd now returns -EPROBE_DEFER in kgd2kfd_init() when it is
not yet loaded.

This patch defers radeon loading by propagating -EPROBE_DEFER to the
kernel's drivers loading infrastructure. That will put radeon into the
pending drivers list (see description in dd.c). Once amdkfd is loaded,
a call to kgd2kfd_init() will return successfully and radeon will be
able to load.

Signed-off-by: Oded Gabbay <oded.gabbay@gmail.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>

+21 -16
+8 -2
drivers/gpu/drm/radeon/radeon_drv.c
··· 322 322 int ret; 323 323 324 324 /* 325 + * Initialize amdkfd before starting radeon. If it was not loaded yet, 326 + * defer radeon probing 327 + */ 328 + ret = radeon_kfd_init(); 329 + if (ret == -EPROBE_DEFER) 330 + return ret; 331 + 332 + /* 325 333 * apple-gmux is needed on dual GPU MacBook Pro 326 334 * to probe the panel if we're the inactive GPU. 327 335 */ ··· 588 580 DRM_ERROR("No UMS support in radeon module!\n"); 589 581 return -EINVAL; 590 582 } 591 - 592 - radeon_kfd_init(); 593 583 594 584 /* let modprobe override vga console setting */ 595 585 return drm_pci_init(driver, pdriver);
+12 -13
drivers/gpu/drm/radeon/radeon_kfd.c
··· 132 132 133 133 static const struct kgd2kfd_calls *kgd2kfd; 134 134 135 - bool radeon_kfd_init(void) 135 + int radeon_kfd_init(void) 136 136 { 137 + int ret; 138 + 137 139 #if defined(CONFIG_HSA_AMD_MODULE) 138 - bool (*kgd2kfd_init_p)(unsigned, const struct kgd2kfd_calls**); 140 + int (*kgd2kfd_init_p)(unsigned, const struct kgd2kfd_calls**); 139 141 140 142 kgd2kfd_init_p = symbol_request(kgd2kfd_init); 141 143 142 144 if (kgd2kfd_init_p == NULL) 143 - return false; 145 + return -ENOENT; 144 146 145 - if (kgd2kfd_init_p(KFD_INTERFACE_VERSION, &kgd2kfd)) { 147 + ret = kgd2kfd_init_p(KFD_INTERFACE_VERSION, &kgd2kfd); 148 + if (ret) { 146 149 symbol_put(kgd2kfd_init); 147 150 kgd2kfd = NULL; 148 - 149 - return false; 150 151 } 151 152 152 - return true; 153 153 #elif defined(CONFIG_HSA_AMD) 154 - if (kgd2kfd_init(KFD_INTERFACE_VERSION, &kgd2kfd)) { 154 + ret = kgd2kfd_init(KFD_INTERFACE_VERSION, &kgd2kfd); 155 + if (ret) 155 156 kgd2kfd = NULL; 156 157 157 - return false; 158 - } 159 - 160 - return true; 161 158 #else 162 - return false; 159 + ret = -ENOENT; 163 160 #endif 161 + 162 + return ret; 164 163 } 165 164 166 165 void radeon_kfd_fini(void)
+1 -1
drivers/gpu/drm/radeon/radeon_kfd.h
··· 33 33 34 34 struct radeon_device; 35 35 36 - bool radeon_kfd_init(void); 36 + int radeon_kfd_init(void); 37 37 void radeon_kfd_fini(void); 38 38 39 39 void radeon_kfd_suspend(struct radeon_device *rdev);