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)