mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-23 01:50:07 +03:00
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:
committed by
mobile promotions
parent
7eb59ff8d3
commit
a9c66768db
@@ -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 \
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
* more details.
|
||||
*/
|
||||
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
114
drivers/gpu/nvgpu/common/linux/firmware.c
Normal file
114
drivers/gpu/nvgpu/common/linux/firmware.c
Normal 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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
66
drivers/gpu/nvgpu/include/nvgpu/firmware.h
Normal file
66
drivers/gpu/nvgpu/include/nvgpu/firmware.h
Normal 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
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user