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 <tbergstrom@nvidia.com>
Reviewed-on: http://git-master/r/1463538
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
Terje Bergstrom
2017-04-14 12:06:39 -07:00
committed by mobile promotions
parent 7eb59ff8d3
commit a9c66768db
15 changed files with 251 additions and 139 deletions

View File

@@ -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 \

View File

@@ -11,7 +11,6 @@
* more details.
*/
#include <linux/firmware.h>
#include <linux/module.h>
#include <linux/uaccess.h>

View File

@@ -15,7 +15,6 @@
*/
#include <linux/dma-mapping.h>
#include <linux/firmware.h>
#include <nvgpu/kmem.h>
#include <nvgpu/nvgpu_common.h>
@@ -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.
*

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#include <linux/firmware.h>
#include <nvgpu/kmem.h>
#include <nvgpu/bug.h>
#include <nvgpu/firmware.h>
#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);
}

View File

@@ -17,7 +17,6 @@
*/
#include <linux/dma-mapping.h>
#include <linux/firmware.h>
#include <linux/fs.h>
#include <linux/debugfs.h>
#include <linux/dma-buf.h>
@@ -30,6 +29,7 @@
#include <nvgpu/kmem.h>
#include <nvgpu/log.h>
#include <nvgpu/bug.h>
#include <nvgpu/firmware.h>
#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;
}

View File

@@ -19,11 +19,10 @@
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <linux/firmware.h>
#include <nvgpu/nvgpu_common.h>
#include <nvgpu/kmem.h>
#include <nvgpu/log.h>
#include <nvgpu/firmware.h>
#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;
}

View File

@@ -17,7 +17,6 @@
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <linux/firmware.h>
#include <trace/events/gk20a.h>
#include <nvgpu/dma.h>
@@ -28,6 +27,7 @@
#include <nvgpu/bsearch.h>
#include <nvgpu/sort.h>
#include <nvgpu/bug.h>
#include <nvgpu/firmware.h>
#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;

View File

@@ -16,7 +16,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/firmware.h>
#include <linux/module.h>
#include <linux/debugfs.h>
#include <linux/uaccess.h>
@@ -27,6 +26,7 @@
#include <nvgpu/dma.h>
#include <nvgpu/log.h>
#include <nvgpu/bug.h>
#include <nvgpu/firmware.h>
#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;

View File

@@ -25,6 +25,8 @@
#include <nvgpu/flcnif_cmn.h>
#include <nvgpu/pmuif/nvgpu_gpmu_cmdif.h>
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);

View File

@@ -11,13 +11,13 @@
* more details.
*/
#include <linux/firmware.h>
#include <linux/pci.h>
#include <nvgpu/bios.h>
#include <nvgpu/kmem.h>
#include <nvgpu/nvgpu_common.h>
#include <nvgpu/timers.h>
#include <nvgpu/firmware.h>
#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;
}

View File

@@ -11,7 +11,6 @@
* more details.
*/
#include <linux/firmware.h>
#include <linux/debugfs.h>
#include <linux/platform/tegra/mc.h>
@@ -21,6 +20,7 @@
#include <nvgpu/nvgpu_common.h>
#include <nvgpu/kmem.h>
#include <nvgpu/acr/nvgpu_acr.h>
#include <nvgpu/firmware.h>
#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;
}

View File

@@ -11,13 +11,13 @@
* more details.
*/
#include <linux/firmware.h>
#include <linux/debugfs.h>
#include <nvgpu/nvgpu_common.h>
#include <nvgpu/kmem.h>
#include <nvgpu/dma.h>
#include <nvgpu/acr/nvgpu_acr.h>
#include <nvgpu/firmware.h>
#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;
}

View File

@@ -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;
};

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#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 <SOC_NAME>.
*
* nvgpu_request_firmware() will load firmware from:
*
* <system firmware load path>/<GPU name>/<fw_name>
*
* If that fails and NO_SOC is not enabled, it'll try next from:
*
* <system firmware load path>/<SOC name>/<fw_name>
*
* 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

View File

@@ -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