From a9c66768db400a82575a82ecddec71f1d3fd4aba Mon Sep 17 00:00:00 2001 From: Terje Bergstrom Date: Fri, 14 Apr 2017 12:06:39 -0700 Subject: gpu: nvgpu: Add abstraction for firmware loading Add nvgpu_firmware data structure, and return it instead of Linux struct firmare from nvgpu_request_firmware. Also add abstraction for releasing firmware: nvgpu_release_firmware. JIRA NVGPU-16 Change-Id: I6dae8262957c0d4506f710289e3a43a6c1729fc7 Signed-off-by: Terje Bergstrom Reviewed-on: http://git-master/r/1463538 Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/gpu/nvgpu/Makefile.nvgpu | 1 + drivers/gpu/nvgpu/boardobj/boardobj.c | 1 - drivers/gpu/nvgpu/common/linux/driver_common.c | 66 -------------- drivers/gpu/nvgpu/common/linux/firmware.c | 114 ++++++++++++++++++++++++ drivers/gpu/nvgpu/gk20a/cde_gk20a.c | 20 ++--- drivers/gpu/nvgpu/gk20a/gr_ctx_gk20a.c | 9 +- drivers/gpu/nvgpu/gk20a/gr_gk20a.c | 16 ++-- drivers/gpu/nvgpu/gk20a/pmu_gk20a.c | 8 +- drivers/gpu/nvgpu/gk20a/pmu_gk20a.h | 4 +- drivers/gpu/nvgpu/gm206/bios_gm206.c | 8 +- drivers/gpu/nvgpu/gm20b/acr_gm20b.c | 32 +++---- drivers/gpu/nvgpu/gp106/acr_gp106.c | 28 +++--- drivers/gpu/nvgpu/include/nvgpu/acr/nvgpu_acr.h | 10 ++- drivers/gpu/nvgpu/include/nvgpu/firmware.h | 66 ++++++++++++++ drivers/gpu/nvgpu/include/nvgpu/nvgpu_common.h | 7 -- 15 files changed, 251 insertions(+), 139 deletions(-) create mode 100644 drivers/gpu/nvgpu/common/linux/firmware.c create mode 100644 drivers/gpu/nvgpu/include/nvgpu/firmware.h (limited to 'drivers') diff --git a/drivers/gpu/nvgpu/Makefile.nvgpu b/drivers/gpu/nvgpu/Makefile.nvgpu index 983df242..6bac840f 100644 --- a/drivers/gpu/nvgpu/Makefile.nvgpu +++ b/drivers/gpu/nvgpu/Makefile.nvgpu @@ -36,6 +36,7 @@ nvgpu-y := \ common/linux/dma.o \ common/linux/soc.o \ common/linux/driver_common.o \ + common/linux/firmware.o \ common/mm/nvgpu_allocator.o \ common/mm/bitmap_allocator.o \ common/mm/buddy_allocator.o \ diff --git a/drivers/gpu/nvgpu/boardobj/boardobj.c b/drivers/gpu/nvgpu/boardobj/boardobj.c index b955f2b4..7ac0eac1 100644 --- a/drivers/gpu/nvgpu/boardobj/boardobj.c +++ b/drivers/gpu/nvgpu/boardobj/boardobj.c @@ -11,7 +11,6 @@ * more details. */ -#include #include #include diff --git a/drivers/gpu/nvgpu/common/linux/driver_common.c b/drivers/gpu/nvgpu/common/linux/driver_common.c index 5c96b4e8..af26996b 100644 --- a/drivers/gpu/nvgpu/common/linux/driver_common.c +++ b/drivers/gpu/nvgpu/common/linux/driver_common.c @@ -15,7 +15,6 @@ */ #include -#include #include #include @@ -201,71 +200,6 @@ int nvgpu_probe(struct gk20a *g, return 0; } -static const struct firmware *do_request_firmware(struct device *dev, - const char *prefix, const char *fw_name, int flags) -{ - const struct firmware *fw; - char *fw_path = NULL; - int path_len, err; - - if (prefix) { - path_len = strlen(prefix) + strlen(fw_name); - path_len += 2; /* for the path separator and zero terminator*/ - - fw_path = nvgpu_kzalloc(get_gk20a(dev), - sizeof(*fw_path) * path_len); - if (!fw_path) - return NULL; - - sprintf(fw_path, "%s/%s", prefix, fw_name); - fw_name = fw_path; - } - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0) - err = request_firmware(&fw, fw_name, dev); -#else - if (flags & NVGPU_REQUEST_FIRMWARE_NO_WARN) - err = request_firmware_direct(&fw, fw_name, dev); - else - err = request_firmware(&fw, fw_name, dev); -#endif - - nvgpu_kfree(get_gk20a(dev), fw_path); - if (err) - return NULL; - return fw; -} - -/* This is a simple wrapper around request_firmware that takes 'fw_name' and - * applies an IP specific relative path prefix to it. The caller is - * responsible for calling release_firmware later. */ -const struct firmware *nvgpu_request_firmware(struct gk20a *g, - const char *fw_name, - int flags) -{ - struct device *dev = g->dev; - const struct firmware *fw; - - /* current->fs is NULL when calling from SYS_EXIT. - Add a check here to prevent crash in request_firmware */ - if (!current->fs || !fw_name) - return NULL; - - BUG_ON(!g->name); - fw = do_request_firmware(dev, g->name, fw_name, flags); - -#ifdef CONFIG_TEGRA_GK20A - /* TO BE REMOVED - Support loading from legacy SOC specific path. */ - if (!fw && !(flags & NVGPU_REQUEST_FIRMWARE_NO_SOC)) { - struct gk20a_platform *platform = gk20a_get_platform(dev); - fw = do_request_firmware(dev, - platform->soc_name, fw_name, flags); - } -#endif - - return fw; -} - /** * cyclic_delta - Returns delta of cyclic integers a and b. * diff --git a/drivers/gpu/nvgpu/common/linux/firmware.c b/drivers/gpu/nvgpu/common/linux/firmware.c new file mode 100644 index 00000000..32b1e61f --- /dev/null +++ b/drivers/gpu/nvgpu/common/linux/firmware.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +#include +#include +#include + +#include "gk20a/gk20a.h" + +static const struct firmware *do_request_firmware(struct device *dev, + const char *prefix, const char *fw_name, int flags) +{ + const struct firmware *fw; + char *fw_path = NULL; + int path_len, err; + + if (prefix) { + path_len = strlen(prefix) + strlen(fw_name); + path_len += 2; /* for the path separator and zero terminator*/ + + fw_path = nvgpu_kzalloc(get_gk20a(dev), + sizeof(*fw_path) * path_len); + if (!fw_path) + return NULL; + + sprintf(fw_path, "%s/%s", prefix, fw_name); + fw_name = fw_path; + } + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0) + err = request_firmware(&fw, fw_name, dev); +#else + if (flags & NVGPU_REQUEST_FIRMWARE_NO_WARN) + err = request_firmware_direct(&fw, fw_name, dev); + else + err = request_firmware(&fw, fw_name, dev); +#endif + + nvgpu_kfree(get_gk20a(dev), fw_path); + if (err) + return NULL; + return fw; +} + +/* This is a simple wrapper around request_firmware that takes 'fw_name' and + * applies an IP specific relative path prefix to it. The caller is + * responsible for calling nvgpu_release_firmware later. */ +struct nvgpu_firmware *nvgpu_request_firmware(struct gk20a *g, + const char *fw_name, + int flags) +{ + struct device *dev = g->dev; + struct nvgpu_firmware *fw; + const struct firmware *linux_fw; + + /* current->fs is NULL when calling from SYS_EXIT. + Add a check here to prevent crash in request_firmware */ + if (!current->fs || !fw_name) + return NULL; + + fw = nvgpu_kzalloc(g, sizeof(*fw)); + if (!fw) + return NULL; + + linux_fw = do_request_firmware(dev, g->name, fw_name, flags); + +#ifdef CONFIG_TEGRA_GK20A + /* TO BE REMOVED - Support loading from legacy SOC specific path. */ + if (!linux_fw && !(flags & NVGPU_REQUEST_FIRMWARE_NO_SOC)) { + struct gk20a_platform *platform = gk20a_get_platform(dev); + linux_fw = do_request_firmware(dev, + platform->soc_name, fw_name, flags); + } +#endif + + if (!linux_fw) + goto err; + + fw->data = nvgpu_kmalloc(g, linux_fw->size); + if (!fw->data) + goto err; + + memcpy(fw->data, linux_fw->data, linux_fw->size); + fw->size = linux_fw->size; + + release_firmware(linux_fw); + + return fw; + +err: + nvgpu_kfree(g, fw); + return NULL; +} + +void nvgpu_release_firmware(struct gk20a *g, struct nvgpu_firmware *fw) +{ + nvgpu_kfree(g, fw->data); + nvgpu_kfree(g, fw); +} diff --git a/drivers/gpu/nvgpu/gk20a/cde_gk20a.c b/drivers/gpu/nvgpu/gk20a/cde_gk20a.c index 2187e833..18432c55 100644 --- a/drivers/gpu/nvgpu/gk20a/cde_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/cde_gk20a.c @@ -17,7 +17,6 @@ */ #include -#include #include #include #include @@ -30,6 +29,7 @@ #include #include #include +#include #include "gk20a.h" #include "channel_gk20a.h" @@ -226,7 +226,7 @@ out: } static int gk20a_init_cde_buf(struct gk20a_cde_ctx *cde_ctx, - const struct firmware *img, + struct nvgpu_firmware *img, struct gk20a_cde_hdr_buf *buf) { struct nvgpu_mem *mem; @@ -314,7 +314,7 @@ static int gk20a_replace_data(struct gk20a_cde_ctx *cde_ctx, void *target, } static int gk20a_init_cde_replace(struct gk20a_cde_ctx *cde_ctx, - const struct firmware *img, + struct nvgpu_firmware *img, struct gk20a_cde_hdr_replace *replace) { struct nvgpu_mem *source_mem; @@ -454,7 +454,7 @@ static int gk20a_cde_patch_params(struct gk20a_cde_ctx *cde_ctx) } static int gk20a_init_cde_param(struct gk20a_cde_ctx *cde_ctx, - const struct firmware *img, + struct nvgpu_firmware *img, struct gk20a_cde_hdr_param *param) { struct nvgpu_mem *target_mem; @@ -497,7 +497,7 @@ static int gk20a_init_cde_param(struct gk20a_cde_ctx *cde_ctx, } static int gk20a_init_cde_required_class(struct gk20a_cde_ctx *cde_ctx, - const struct firmware *img, + struct nvgpu_firmware *img, u32 required_class) { struct gk20a *g = cde_ctx->g; @@ -521,7 +521,7 @@ static int gk20a_init_cde_required_class(struct gk20a_cde_ctx *cde_ctx, } static int gk20a_init_cde_command(struct gk20a_cde_ctx *cde_ctx, - const struct firmware *img, + struct nvgpu_firmware *img, u32 op, struct gk20a_cde_cmd_elem *cmd_elem, u32 num_elems) @@ -622,7 +622,7 @@ static int gk20a_cde_pack_cmdbufs(struct gk20a_cde_ctx *cde_ctx) } static int gk20a_init_cde_img(struct gk20a_cde_ctx *cde_ctx, - const struct firmware *img) + struct nvgpu_firmware *img) { struct gk20a *g = cde_ctx->g; struct gk20a_cde_app *cde_app = &cde_ctx->g->cde_app; @@ -1202,7 +1202,7 @@ __releases(&cde_app->mutex) static int gk20a_cde_load(struct gk20a_cde_ctx *cde_ctx) { struct gk20a *g = cde_ctx->g; - const struct firmware *img; + struct nvgpu_firmware *img; struct channel_gk20a *ch; struct gr_gk20a *gr = &g->gr; int err = 0; @@ -1265,7 +1265,7 @@ static int gk20a_cde_load(struct gk20a_cde_ctx *cde_ctx) } /* initialisation done */ - release_firmware(img); + nvgpu_release_firmware(g, img); return 0; @@ -1276,7 +1276,7 @@ err_alloc_gpfifo: gk20a_vm_put(ch->vm); err_commit_va: err_get_gk20a_channel: - release_firmware(img); + nvgpu_release_firmware(g, img); nvgpu_err(g, "cde: couldn't initialise buffer converter: %d", err); return err; } diff --git a/drivers/gpu/nvgpu/gk20a/gr_ctx_gk20a.c b/drivers/gpu/nvgpu/gk20a/gr_ctx_gk20a.c index 712359e1..3c6d8924 100644 --- a/drivers/gpu/nvgpu/gk20a/gr_ctx_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gr_ctx_gk20a.c @@ -19,11 +19,10 @@ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ -#include - #include #include #include +#include #include "gk20a.h" #include "gr_ctx_gk20a.h" @@ -112,7 +111,7 @@ static bool gr_gk20a_is_firmware_defined(void) static int gr_gk20a_init_ctx_vars_fw(struct gk20a *g, struct gr_gk20a *gr) { - const struct firmware *netlist_fw; + struct nvgpu_firmware *netlist_fw; struct netlist_image *netlist = NULL; char name[MAX_NETLIST_NAME]; u32 i, major_v = ~0, major_v_hw, netlist_num; @@ -392,7 +391,7 @@ static int gr_gk20a_init_ctx_vars_fw(struct gk20a *g, struct gr_gk20a *gr) g->gr.ctx_vars.valid = true; g->gr.netlist = net; - release_firmware(netlist_fw); + nvgpu_release_firmware(g, netlist_fw); gk20a_dbg_fn("done"); goto done; @@ -427,7 +426,7 @@ clean_up: nvgpu_kfree(g, g->gr.ctx_vars.ctxsw_regs.perf_pma.l); nvgpu_kfree(g, g->gr.ctx_vars.ctxsw_regs.pm_rop.l); nvgpu_kfree(g, g->gr.ctx_vars.ctxsw_regs.pm_ucgpc.l); - release_firmware(netlist_fw); + nvgpu_release_firmware(g, netlist_fw); err = -ENOENT; } diff --git a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c index a4419885..0e787356 100644 --- a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c @@ -17,7 +17,6 @@ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ -#include #include #include @@ -28,6 +27,7 @@ #include #include #include +#include #include "gk20a.h" #include "kind_gk20a.h" @@ -2272,8 +2272,8 @@ int gr_gk20a_init_ctxsw_ucode(struct gk20a *g) struct vm_gk20a *vm = &mm->pmu.vm; struct gk20a_ctxsw_bootloader_desc *fecs_boot_desc; struct gk20a_ctxsw_bootloader_desc *gpccs_boot_desc; - const struct firmware *fecs_fw; - const struct firmware *gpccs_fw; + struct nvgpu_firmware *fecs_fw; + struct nvgpu_firmware *gpccs_fw; u32 *fecs_boot_image; u32 *gpccs_boot_image; struct gk20a_ctxsw_ucode_info *ucode_info = &g->ctxsw_ucode_info; @@ -2292,7 +2292,7 @@ int gr_gk20a_init_ctxsw_ucode(struct gk20a *g) gpccs_fw = nvgpu_request_firmware(g, GK20A_GPCCS_UCODE_IMAGE, 0); if (!gpccs_fw) { - release_firmware(fecs_fw); + nvgpu_release_firmware(g, fecs_fw); nvgpu_err(g, "failed to load gpccs ucode!!"); return -ENOENT; } @@ -2321,7 +2321,7 @@ int gr_gk20a_init_ctxsw_ucode(struct gk20a *g) g->gr.ctx_vars.ucode.fecs.inst.l, g->gr.ctx_vars.ucode.fecs.data.l); - release_firmware(fecs_fw); + nvgpu_release_firmware(g, fecs_fw); fecs_fw = NULL; gr_gk20a_copy_ctxsw_ucode_segments(g, &ucode_info->surface_desc, @@ -2330,7 +2330,7 @@ int gr_gk20a_init_ctxsw_ucode(struct gk20a *g) g->gr.ctx_vars.ucode.gpccs.inst.l, g->gr.ctx_vars.ucode.gpccs.data.l); - release_firmware(gpccs_fw); + nvgpu_release_firmware(g, gpccs_fw); gpccs_fw = NULL; err = gr_gk20a_init_ctxsw_ucode_vaspace(g); @@ -2345,9 +2345,9 @@ int gr_gk20a_init_ctxsw_ucode(struct gk20a *g) ucode_info->surface_desc.size, gk20a_mem_flag_none); nvgpu_dma_free(g, &ucode_info->surface_desc); - release_firmware(gpccs_fw); + nvgpu_release_firmware(g, gpccs_fw); gpccs_fw = NULL; - release_firmware(fecs_fw); + nvgpu_release_firmware(g, fecs_fw); fecs_fw = NULL; return err; diff --git a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c index 49b9e78d..0ca8851f 100644 --- a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c @@ -16,7 +16,6 @@ * along with this program. If not, see . */ -#include #include #include #include @@ -27,6 +26,7 @@ #include #include #include +#include #include "gk20a.h" #include "gr_gk20a.h" @@ -3099,12 +3099,14 @@ static int pmu_queue_close(struct pmu_gk20a *pmu, void gk20a_remove_pmu_support(struct pmu_gk20a *pmu) { + struct gk20a *g = gk20a_from_pmu(pmu); + gk20a_dbg_fn(""); if (nvgpu_alloc_initialized(&pmu->dmem)) nvgpu_alloc_destroy(&pmu->dmem); - release_firmware(pmu->fw); + nvgpu_release_firmware(g, pmu->fw); nvgpu_mutex_destroy(&pmu->elpg_mutex); nvgpu_mutex_destroy(&pmu->pg_mutex); @@ -3157,7 +3159,7 @@ static int gk20a_prepare_ucode(struct gk20a *g) return gk20a_init_pmu(pmu); err_release_fw: - release_firmware(pmu->fw); + nvgpu_release_firmware(g, pmu->fw); pmu->fw = NULL; return err; diff --git a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h index 84161304..e7a8b7c2 100644 --- a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h @@ -25,6 +25,8 @@ #include #include +struct nvgpu_firmware; + /* defined by pmu hw spec */ #define GK20A_PMU_VA_SIZE (512 * 1024 * 1024) #define GK20A_PMU_UCODE_SIZE_MAX (256 * 1024) @@ -394,7 +396,7 @@ struct pmu_gk20a { u32 aelpg_param[5]; u32 override_done; - const struct firmware *fw; + struct nvgpu_firmware *fw; }; int gk20a_init_pmu_support(struct gk20a *g); diff --git a/drivers/gpu/nvgpu/gm206/bios_gm206.c b/drivers/gpu/nvgpu/gm206/bios_gm206.c index 2c84ac62..f460a053 100644 --- a/drivers/gpu/nvgpu/gm206/bios_gm206.c +++ b/drivers/gpu/nvgpu/gm206/bios_gm206.c @@ -11,13 +11,13 @@ * more details. */ -#include #include #include #include #include #include +#include #include "gk20a/gk20a.h" #include "gm20b/fifo_gm20b.h" @@ -249,7 +249,7 @@ int gm206_bios_init(struct gk20a *g) unsigned int i; struct gk20a_platform *platform = dev_get_drvdata(g->dev); struct dentry *d; - const struct firmware *bios_fw; + struct nvgpu_firmware *bios_fw; int err; struct pci_dev *pdev = to_pci_dev(g->dev); char rom_name[sizeof(BIOS_OVERLAY_NAME_FORMATTED)]; @@ -273,7 +273,7 @@ int gm206_bios_init(struct gk20a *g) memcpy(g->bios.data, &bios_fw->data[ROM_FILE_PAYLOAD_OFFSET], g->bios.size); - release_firmware(bios_fw); + nvgpu_release_firmware(g, bios_fw); } else { gk20a_dbg_info("reading bios from EEPROM"); g->bios.size = BIOS_SIZE; @@ -336,7 +336,7 @@ int gm206_bios_init(struct gk20a *g) return 0; free_firmware: - release_firmware(bios_fw); + nvgpu_release_firmware(g, bios_fw); return err; } diff --git a/drivers/gpu/nvgpu/gm20b/acr_gm20b.c b/drivers/gpu/nvgpu/gm20b/acr_gm20b.c index c593dd7c..b6afa748 100644 --- a/drivers/gpu/nvgpu/gm20b/acr_gm20b.c +++ b/drivers/gpu/nvgpu/gm20b/acr_gm20b.c @@ -11,7 +11,6 @@ * more details. */ -#include #include #include @@ -21,6 +20,7 @@ #include #include #include +#include #include "gk20a/gk20a.h" #include "gk20a/pmu_gk20a.h" @@ -123,7 +123,7 @@ void gm20b_init_secure_pmu(struct gpu_ops *gops) static int pmu_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img) { - const struct firmware *pmu_fw, *pmu_desc, *pmu_sig; + struct nvgpu_firmware *pmu_fw, *pmu_desc, *pmu_sig; struct pmu_gk20a *pmu = &g->pmu; struct lsf_ucode_desc *lsf_desc; int err; @@ -174,21 +174,21 @@ static int pmu_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img) p_img->header = NULL; p_img->lsf_desc = (struct lsf_ucode_desc *)lsf_desc; gm20b_dbg_pmu("requesting PMU ucode in GM20B exit\n"); - release_firmware(pmu_sig); + nvgpu_release_firmware(g, pmu_sig); return 0; release_sig: - release_firmware(pmu_sig); + nvgpu_release_firmware(g, pmu_sig); release_desc: - release_firmware(pmu_desc); + nvgpu_release_firmware(g, pmu_desc); release_img_fw: - release_firmware(pmu_fw); + nvgpu_release_firmware(g, pmu_fw); return err; } static int fecs_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img) { struct lsf_ucode_desc *lsf_desc; - const struct firmware *fecs_sig; + struct nvgpu_firmware *fecs_sig; int err; fecs_sig = nvgpu_request_firmware(g, GM20B_FECS_UCODE_SIG, 0); @@ -244,18 +244,18 @@ static int fecs_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img) p_img->header = NULL; p_img->lsf_desc = (struct lsf_ucode_desc *)lsf_desc; gm20b_dbg_pmu("fecs fw loaded\n"); - release_firmware(fecs_sig); + nvgpu_release_firmware(g, fecs_sig); return 0; free_lsf_desc: nvgpu_kfree(g, lsf_desc); rel_sig: - release_firmware(fecs_sig); + nvgpu_release_firmware(g, fecs_sig); return err; } static int gpccs_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img) { struct lsf_ucode_desc *lsf_desc; - const struct firmware *gpccs_sig; + struct nvgpu_firmware *gpccs_sig; int err; if (g->ops.securegpccs == false) @@ -315,12 +315,12 @@ static int gpccs_ucode_details(struct gk20a *g, struct flcn_ucode_img *p_img) p_img->header = NULL; p_img->lsf_desc = (struct lsf_ucode_desc *)lsf_desc; gm20b_dbg_pmu("gpccs fw loaded\n"); - release_firmware(gpccs_sig); + nvgpu_release_firmware(g, gpccs_sig); return 0; free_lsf_desc: nvgpu_kfree(g, lsf_desc); rel_sig: - release_firmware(gpccs_sig); + nvgpu_release_firmware(g, gpccs_sig); return err; } @@ -1070,7 +1070,7 @@ static int gm20b_bootstrap_hs_flcn(struct gk20a *g) u32 status, size; u64 start; struct acr_desc *acr = &g->acr; - const struct firmware *acr_fw = acr->acr_fw; + struct nvgpu_firmware *acr_fw = acr->acr_fw; struct flcn_bl_dmem_desc *bl_dmem_desc = &acr->bl_dmem_desc; u32 *acr_ucode_header_t210_load; u32 *acr_ucode_data_t210_load; @@ -1169,7 +1169,7 @@ static int gm20b_bootstrap_hs_flcn(struct gk20a *g) err_free_ucode_map: nvgpu_dma_unmap_free(vm, &acr->acr_ucode); err_release_acr_fw: - release_firmware(acr_fw); + nvgpu_release_firmware(g, acr_fw); acr->acr_fw = NULL; return err; } @@ -1385,7 +1385,7 @@ int pmu_exec_gen_bl(struct gk20a *g, void *desc, u8 b_wait_for_halt) int err = 0; u32 bl_sz; struct acr_desc *acr = &g->acr; - const struct firmware *hsbl_fw = acr->hsbl_fw; + struct nvgpu_firmware *hsbl_fw = acr->hsbl_fw; struct hsflcn_bl_desc *pmu_bl_gm10x_desc; u32 *pmu_bl_gm10x = NULL; gm20b_dbg_pmu(""); @@ -1472,7 +1472,7 @@ err_unmap_bl: err_free_ucode: nvgpu_dma_free(g, &acr->hsbl_ucode); err_done: - release_firmware(hsbl_fw); + nvgpu_release_firmware(g, hsbl_fw); return err; } diff --git a/drivers/gpu/nvgpu/gp106/acr_gp106.c b/drivers/gpu/nvgpu/gp106/acr_gp106.c index da281077..c4045cb6 100644 --- a/drivers/gpu/nvgpu/gp106/acr_gp106.c +++ b/drivers/gpu/nvgpu/gp106/acr_gp106.c @@ -11,13 +11,13 @@ * more details. */ -#include #include #include #include #include #include +#include #include "gk20a/gk20a.h" #include "gk20a/pmu_gk20a.h" @@ -137,7 +137,7 @@ void gp106_init_secure_pmu(struct gpu_ops *gops) static int pmu_ucode_details(struct gk20a *g, struct flcn_ucode_img_v1 *p_img) { - const struct firmware *pmu_fw, *pmu_desc, *pmu_sig; + struct nvgpu_firmware *pmu_fw, *pmu_desc, *pmu_sig; struct pmu_gk20a *pmu = &g->pmu; struct lsf_ucode_desc_v1 *lsf_desc; int err; @@ -194,14 +194,14 @@ static int pmu_ucode_details(struct gk20a *g, struct flcn_ucode_img_v1 *p_img) p_img->lsf_desc = (struct lsf_ucode_desc_v1 *)lsf_desc; gp106_dbg_pmu("requesting PMU ucode in GM20B exit\n"); - release_firmware(pmu_sig); + nvgpu_release_firmware(g, pmu_sig); return 0; release_sig: - release_firmware(pmu_sig); + nvgpu_release_firmware(g, pmu_sig); release_desc: - release_firmware(pmu_desc); + nvgpu_release_firmware(g, pmu_desc); release_img_fw: - release_firmware(pmu_fw); + nvgpu_release_firmware(g, pmu_fw); return err; } @@ -209,7 +209,7 @@ static int fecs_ucode_details(struct gk20a *g, struct flcn_ucode_img_v1 *p_img) { u32 ver = g->gpu_characteristics.arch + g->gpu_characteristics.impl; struct lsf_ucode_desc_v1 *lsf_desc; - const struct firmware *fecs_sig = NULL; + struct nvgpu_firmware *fecs_sig = NULL; int err; switch (ver) { @@ -279,12 +279,12 @@ static int fecs_ucode_details(struct gk20a *g, struct flcn_ucode_img_v1 *p_img) p_img->header = NULL; p_img->lsf_desc = (struct lsf_ucode_desc_v1 *)lsf_desc; gp106_dbg_pmu("fecs fw loaded\n"); - release_firmware(fecs_sig); + nvgpu_release_firmware(g, fecs_sig); return 0; free_lsf_desc: nvgpu_kfree(g, lsf_desc); rel_sig: - release_firmware(fecs_sig); + nvgpu_release_firmware(g, fecs_sig); return err; } @@ -292,7 +292,7 @@ static int gpccs_ucode_details(struct gk20a *g, struct flcn_ucode_img_v1 *p_img) { u32 ver = g->gpu_characteristics.arch + g->gpu_characteristics.impl; struct lsf_ucode_desc_v1 *lsf_desc; - const struct firmware *gpccs_sig = NULL; + struct nvgpu_firmware *gpccs_sig = NULL; int err; if (g->ops.securegpccs == false) @@ -366,12 +366,12 @@ static int gpccs_ucode_details(struct gk20a *g, struct flcn_ucode_img_v1 *p_img) p_img->header = NULL; p_img->lsf_desc = (struct lsf_ucode_desc_v1 *)lsf_desc; gp106_dbg_pmu("gpccs fw loaded\n"); - release_firmware(gpccs_sig); + nvgpu_release_firmware(g, gpccs_sig); return 0; free_lsf_desc: nvgpu_kfree(g, lsf_desc); rel_sig: - release_firmware(gpccs_sig); + nvgpu_release_firmware(g, gpccs_sig); return err; } @@ -1048,7 +1048,7 @@ static int gp106_bootstrap_hs_flcn(struct gk20a *g) u32 img_size_in_bytes = 0; u32 status; struct acr_desc *acr = &g->acr; - const struct firmware *acr_fw = acr->acr_fw; + struct nvgpu_firmware *acr_fw = acr->acr_fw; struct flcn_bl_dmem_desc_v1 *bl_dmem_desc = &acr->bl_dmem_desc_v1; u32 *acr_ucode_header_t210_load; u32 *acr_ucode_data_t210_load; @@ -1167,7 +1167,7 @@ static int gp106_bootstrap_hs_flcn(struct gk20a *g) err_free_ucode_map: nvgpu_dma_unmap_free(vm, &acr->acr_ucode); err_release_acr_fw: - release_firmware(acr_fw); + nvgpu_release_firmware(g, acr_fw); acr->acr_fw = NULL; return err; } diff --git a/drivers/gpu/nvgpu/include/nvgpu/acr/nvgpu_acr.h b/drivers/gpu/nvgpu/include/nvgpu/acr/nvgpu_acr.h index 6991a0ba..3844362d 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/acr/nvgpu_acr.h +++ b/drivers/gpu/nvgpu/include/nvgpu/acr/nvgpu_acr.h @@ -21,6 +21,8 @@ #include "acr_objlsfm.h" #include "acr_objflcn.h" +struct nvgpu_firmware; + #define MAX_SUPPORTED_LSFM 3 /*PMU, FECS, GPCCS*/ #define ACR_COMPLETION_TIMEOUT_MS 10000 /*in msec */ @@ -74,20 +76,20 @@ struct acr_desc { struct bin_hdr *hsbin_hdr; struct acr_fw_header *fw_hdr; u32 pmu_args; - const struct firmware *acr_fw; + struct nvgpu_firmware *acr_fw; union{ struct flcn_acr_desc *acr_dmem_desc; struct flcn_acr_desc_v1 *acr_dmem_desc_v1; }; struct nvgpu_mem acr_ucode; - const struct firmware *hsbl_fw; + struct nvgpu_firmware *hsbl_fw; struct nvgpu_mem hsbl_ucode; union { struct flcn_bl_dmem_desc bl_dmem_desc; struct flcn_bl_dmem_desc_v1 bl_dmem_desc_v1; }; - const struct firmware *pmu_fw; - const struct firmware *pmu_desc; + struct nvgpu_firmware *pmu_fw; + struct nvgpu_firmware *pmu_desc; u32 capabilities; }; diff --git a/drivers/gpu/nvgpu/include/nvgpu/firmware.h b/drivers/gpu/nvgpu/include/nvgpu/firmware.h new file mode 100644 index 00000000..cf206dc2 --- /dev/null +++ b/drivers/gpu/nvgpu/include/nvgpu/firmware.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef _NVGPU_FIRMWARE_H_ +#define _NVGPU_FIRMWARE_H_ + +struct gk20a; + +#define NVGPU_REQUEST_FIRMWARE_NO_WARN (1UL << 0) +#define NVGPU_REQUEST_FIRMWARE_NO_SOC (1UL << 1) + +struct nvgpu_firmware { + u8 *data; + size_t size; +}; + +/** + * nvgpu_request_firmware - load a firmware blob from filesystem. + * + * @g The GPU driver struct for device to load firmware for + * @fw_name The base name of the firmware file. + * @flags Flags for loading; + * + * NVGPU_REQUEST_FIRMWARE_NO_WARN: Do not display warning on + * failed load. + * + * NVGPU_REQUEST_FIRMWARE_NO_SOC: Do not attempt loading from + * path . + * + * nvgpu_request_firmware() will load firmware from: + * + * // + * + * If that fails and NO_SOC is not enabled, it'll try next from: + * + * // + * + * It'll allocate a nvgpu_firmware structure and initializes it and returns + * it to caller. + */ +struct nvgpu_firmware *nvgpu_request_firmware(struct gk20a *g, + const char *fw_name, + int flags); + +/** + * nvgpu_release_firmware - free firmware and associated nvgpu_firmware blob + * + * @g The GPU driver struct for device to free firmware for + * @fw The firmware to free. fw blob will also be freed. + */ +void nvgpu_release_firmware(struct gk20a *g, struct nvgpu_firmware *fw); + +#endif diff --git a/drivers/gpu/nvgpu/include/nvgpu/nvgpu_common.h b/drivers/gpu/nvgpu/include/nvgpu/nvgpu_common.h index 85b4a3df..2a9e4f99 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/nvgpu_common.h +++ b/drivers/gpu/nvgpu/include/nvgpu/nvgpu_common.h @@ -25,11 +25,4 @@ int nvgpu_probe(struct gk20a *g, const char *interface_name, struct class *class); -#define NVGPU_REQUEST_FIRMWARE_NO_WARN BIT(0) -#define NVGPU_REQUEST_FIRMWARE_NO_SOC BIT(1) - -const struct firmware *nvgpu_request_firmware(struct gk20a *g, - const char *fw_name, - int flags); - #endif -- cgit v1.2.2