From b3e25e5a5c910ff7f756bd320aebced2f3e973e4 Mon Sep 17 00:00:00 2001 From: "Wang, Yiyang" Date: Tue, 20 Aug 2024 02:33:25 +0000 Subject: [PATCH] dkms: optimize the dg2 kernel driver loading time loaded the dGPU drvier as kernel module on boot stage, before that the driver loaded after init process lunched that took more time for driver working. Tracked-On: OAM-124024 Signed-off-by: Wang, Yiyang --- drivers/gpu/drm/i915/i915_pci.c | 46 ++++++++++++++++++++++++++++++++- kernel/module/main.c | 29 ++++++++++++++++----- 2 files changed, 67 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 23f3eed0a9f3..9448c891a950 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -22,6 +22,8 @@ * */ +#include + #include #include #include @@ -1022,6 +1024,45 @@ static bool intel_mmio_bar_valid(struct pci_dev *pdev, struct intel_device_info return i915_pci_resource_valid(pdev, intel_mmio_bar(intel_info->__runtime.graphics.ip.ver)); } +extern int gfx_load_module(void *buf, int len); + +static void gfx_out_of_tree_load(struct device *dev) +{ + const struct firmware *fw = NULL; + int err; + void *buf; + + err = firmware_request_nowarn(&fw, "i915/compat.ko", dev); + if (err) { + DRM_ERROR("compat load failed: %d\n", err); + return; + } + buf = __vmalloc((unsigned long)fw->size, GFP_KERNEL | __GFP_NOWARN); + memcpy(buf, fw->data, fw->size); + gfx_load_module(buf, fw->size); + DRM_INFO("compat loaded\n"); + + err = firmware_request_nowarn(&fw, "i915/intel_vsec.ko", dev); + if (err) { + DRM_ERROR("intel_vsec load failed: %d\n", err); + return; + } + buf = __vmalloc((unsigned long)fw->size, GFP_KERNEL | __GFP_NOWARN); + memcpy(buf, fw->data, fw->size); + gfx_load_module(buf, fw->size); + DRM_INFO("intel_vsec loaded\n"); + + err = firmware_request_nowarn(&fw, "i915/i915_ag.ko", dev); + if (err) { + DRM_ERROR("i915_ag load failed: %d\n", err); + return; + } + buf = __vmalloc((unsigned long)fw->size, GFP_KERNEL | __GFP_NOWARN); + memcpy(buf, fw->data, fw->size); + gfx_load_module(buf, fw->size); + DRM_INFO("i915_ag loaded\n"); +} + static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct intel_device_info *intel_info = @@ -1147,7 +1188,10 @@ static struct pci_driver i915_pci_driver = { int i915_pci_register_driver(void) { - return pci_register_driver(&i915_pci_driver); + int ret; + ret = pci_register_driver(&i915_pci_driver); + gfx_out_of_tree_load(NULL); + return ret; } void i915_pci_unregister_driver(void) diff --git a/kernel/module/main.c b/kernel/module/main.c index 4460dcce915f..f674c50d2004 100644 --- a/kernel/module/main.c +++ b/kernel/module/main.c @@ -2734,7 +2734,7 @@ static int unknown_module_param_cb(char *param, char *val, const char *modname, * zero, and we rely on this for optional sections. */ static int load_module(struct load_info *info, const char __user *uargs, - int flags) + int flags, bool no_args) { struct module *mod; long err = 0; @@ -2861,10 +2861,17 @@ static int load_module(struct load_info *info, const char __user *uargs, flush_module_icache(mod); /* Now copy in args */ - mod->args = strndup_user(uargs, ~0UL >> 1); - if (IS_ERR(mod->args)) { - err = PTR_ERR(mod->args); - goto free_arch_cleanup; + if (!no_args) { + mod->args = strndup_user(uargs, ~0UL >> 1); + if (IS_ERR(mod->args)) { + pr_debug("%s mod->args error\n", __func__); + err = PTR_ERR(mod->args); + goto free_arch_cleanup; + } + pr_debug("%s mod->args: %llx \n", __func__, (u64)mod->args); + } else { + char *arg = ""; + mod->args = kmemdup(arg, strlen(arg) + 1, GFP_KERNEL); } init_build_id(mod, info); @@ -2977,7 +2984,7 @@ SYSCALL_DEFINE3(init_module, void __user *, umod, if (err) return err; - return load_module(&info, uargs, 0); + return load_module(&info, uargs, 0, false); } SYSCALL_DEFINE3(finit_module, int, fd, const char __user *, uargs, int, flags) @@ -3013,7 +3020,15 @@ SYSCALL_DEFINE3(finit_module, int, fd, const char __user *, uargs, int, flags) info.len = len; } - return load_module(&info, uargs, flags); + return load_module(&info, uargs, flags, false); +} + +int gfx_load_module(void *buf, int len) +{ + struct load_info info = { }; + info.hdr = buf; + info.len = len; + return load_module(&info, NULL, 0, true); } static inline int within(unsigned long addr, void *start, unsigned long size)