drm/radeon: Return -EPROBE_DEFER when amdkfd not loaded
authorOded Gabbay <oded.gabbay@gmail.com>
Tue, 9 Feb 2016 11:30:04 +0000 (13:30 +0200)
committerOded Gabbay <oded.gabbay@gmail.com>
Sat, 27 Feb 2016 20:52:40 +0000 (22:52 +0200)
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>
drivers/gpu/drm/radeon/radeon_drv.c
drivers/gpu/drm/radeon/radeon_kfd.c
drivers/gpu/drm/radeon/radeon_kfd.h

index cad25557650f054746b957bc04ea8a69f3a83e01..ccd4ad4ee59290a53279e930e737f6a2c2b18b27 100644 (file)
@@ -321,6 +321,14 @@ static int radeon_pci_probe(struct pci_dev *pdev,
 {
        int ret;
 
+       /*
+        * Initialize amdkfd before starting radeon. If it was not loaded yet,
+        * defer radeon probing
+        */
+       ret = radeon_kfd_init();
+       if (ret == -EPROBE_DEFER)
+               return ret;
+
        /*
         * apple-gmux is needed on dual GPU MacBook Pro
         * to probe the panel if we're the inactive GPU.
@@ -581,8 +589,6 @@ static int __init radeon_init(void)
                return -EINVAL;
        }
 
-       radeon_kfd_init();
-
        /* let modprobe override vga console setting */
        return drm_pci_init(driver, pdriver);
 }
index 83c2704a72919d6989bfd88f4f449099f2de0c7b..87a9ebb5f58f3befe0e8c1fc697cfcdce09bd078 100644 (file)
@@ -132,35 +132,34 @@ static const struct kfd2kgd_calls kfd2kgd = {
 
 static const struct kgd2kfd_calls *kgd2kfd;
 
-bool radeon_kfd_init(void)
+int radeon_kfd_init(void)
 {
+       int ret;
+
 #if defined(CONFIG_HSA_AMD_MODULE)
-       bool (*kgd2kfd_init_p)(unsigned, const struct kgd2kfd_calls**);
+       int (*kgd2kfd_init_p)(unsigned, const struct kgd2kfd_calls**);
 
        kgd2kfd_init_p = symbol_request(kgd2kfd_init);
 
        if (kgd2kfd_init_p == NULL)
-               return false;
+               return -ENOENT;
 
-       if (kgd2kfd_init_p(KFD_INTERFACE_VERSION, &kgd2kfd)) {
+       ret = kgd2kfd_init_p(KFD_INTERFACE_VERSION, &kgd2kfd);
+       if (ret) {
                symbol_put(kgd2kfd_init);
                kgd2kfd = NULL;
-
-               return false;
        }
 
-       return true;
 #elif defined(CONFIG_HSA_AMD)
-       if (kgd2kfd_init(KFD_INTERFACE_VERSION, &kgd2kfd)) {
+       ret = kgd2kfd_init(KFD_INTERFACE_VERSION, &kgd2kfd);
+       if (ret)
                kgd2kfd = NULL;
 
-               return false;
-       }
-
-       return true;
 #else
-       return false;
+       ret = -ENOENT;
 #endif
+
+       return ret;
 }
 
 void radeon_kfd_fini(void)
index 1103f9082f6b069aa1c4501347ef3066fc1a619a..9df1fea8e971936b70253c002ea6c5113ca8d9e3 100644 (file)
@@ -33,7 +33,7 @@
 
 struct radeon_device;
 
-bool radeon_kfd_init(void);
+int radeon_kfd_init(void);
 void radeon_kfd_fini(void);
 
 void radeon_kfd_suspend(struct radeon_device *rdev);