Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dkms: optimize the dg2 kernel driver loading time #35

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 45 additions & 1 deletion drivers/gpu/drm/i915/i915_pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
*
*/

#include <linux/firmware.h>

#include <drm/drm_color_mgmt.h>
#include <drm/drm_drv.h>
#include <drm/i915_pciids.h>
Expand Down Expand Up @@ -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 =
Expand Down Expand Up @@ -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)
Expand Down
29 changes: 22 additions & 7 deletions kernel/module/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down