Commit 671e2ee5 authored by Dave Airlie's avatar Dave Airlie

Merge branch 'linux-5.2' of git://github.com/skeggsb/linux into drm-fixes

" This is a bit more than I'd like to be pushing at this point in a
cycle, but it's a fairly important issue.  There's been numerous
reports of more recent GP10[2467] boards failing to load, and I've
worked with NVIDIA FW engineers and tracked this down to the FW we've
been using not properly supporting the boards in question.

I've pushed an update to linux-firmware with the new FW version, which
unfortunately contains API changes vs the older firmware.

This series teaches the ACR subsystem inside nouveau enough to be able
to deal with supporting multiple incompatible FW revisions, and adds
support to the relevant chipsets for loading the newer FW revision, if
it's available."
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
From: Ben Skeggs <skeggsb@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/CACAvsv7pG+vur0Kn_TyU3ainnkvJVw07upnnaQNOToF+kzQtDQ@mail.gmail.com
parents e659b412 ab4bec16
/* SPDX-License-Identifier: GPL-2.0 */ /* SPDX-License-Identifier: GPL-2.0 */
#ifndef __NVKM_FIRMWARE_H__ #ifndef __NVKM_FIRMWARE_H__
#define __NVKM_FIRMWARE_H__ #define __NVKM_FIRMWARE_H__
#include <core/subdev.h>
#include <core/device.h>
int nvkm_firmware_get_version(const struct nvkm_subdev *, const char *fwname,
int nvkm_firmware_get(struct nvkm_device *device, const char *fwname, int min_version, int max_version,
const struct firmware **fw); const struct firmware **);
int nvkm_firmware_get(const struct nvkm_subdev *, const char *fwname,
void nvkm_firmware_put(const struct firmware *fw); const struct firmware **);
void nvkm_firmware_put(const struct firmware *);
#endif #endif
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
/** /**
* nvkm_firmware_get - load firmware from the official nvidia/chip/ directory * nvkm_firmware_get - load firmware from the official nvidia/chip/ directory
* @device device that will use that firmware * @subdev subdevice that will use that firmware
* @fwname name of firmware file to load * @fwname name of firmware file to load
* @fw firmware structure to load to * @fw firmware structure to load to
* *
...@@ -32,9 +32,11 @@ ...@@ -32,9 +32,11 @@
* Firmware files released by NVIDIA will always follow this format. * Firmware files released by NVIDIA will always follow this format.
*/ */
int int
nvkm_firmware_get(struct nvkm_device *device, const char *fwname, nvkm_firmware_get_version(const struct nvkm_subdev *subdev, const char *fwname,
int min_version, int max_version,
const struct firmware **fw) const struct firmware **fw)
{ {
struct nvkm_device *device = subdev->device;
char f[64]; char f[64];
char cname[16]; char cname[16];
int i; int i;
...@@ -48,8 +50,29 @@ nvkm_firmware_get(struct nvkm_device *device, const char *fwname, ...@@ -48,8 +50,29 @@ nvkm_firmware_get(struct nvkm_device *device, const char *fwname,
cname[i] = tolower(cname[i]); cname[i] = tolower(cname[i]);
} }
for (i = max_version; i >= min_version; i--) {
if (i != 0)
snprintf(f, sizeof(f), "nvidia/%s/%s-%d.bin", cname, fwname, i);
else
snprintf(f, sizeof(f), "nvidia/%s/%s.bin", cname, fwname); snprintf(f, sizeof(f), "nvidia/%s/%s.bin", cname, fwname);
return request_firmware(fw, f, device->dev);
if (!firmware_request_nowarn(fw, f, device->dev)) {
nvkm_debug(subdev, "firmware \"%s\" loaded\n", f);
return i;
}
nvkm_debug(subdev, "firmware \"%s\" unavailable\n", f);
}
nvkm_error(subdev, "failed to load firmware \"%s\"", fwname);
return -ENOENT;
}
int
nvkm_firmware_get(const struct nvkm_subdev *subdev, const char *fwname,
const struct firmware **fw)
{
return nvkm_firmware_get_version(subdev, fwname, 0, 0, fw);
} }
/** /**
......
...@@ -2115,12 +2115,10 @@ int ...@@ -2115,12 +2115,10 @@ int
gf100_gr_ctor_fw(struct gf100_gr *gr, const char *fwname, gf100_gr_ctor_fw(struct gf100_gr *gr, const char *fwname,
struct gf100_gr_fuc *fuc) struct gf100_gr_fuc *fuc)
{ {
struct nvkm_subdev *subdev = &gr->base.engine.subdev;
struct nvkm_device *device = subdev->device;
const struct firmware *fw; const struct firmware *fw;
int ret; int ret;
ret = nvkm_firmware_get(device, fwname, &fw); ret = nvkm_firmware_get(&gr->base.engine.subdev, fwname, &fw);
if (ret) { if (ret) {
ret = gf100_gr_ctor_fw_legacy(gr, fwname, fuc, ret); ret = gf100_gr_ctor_fw_legacy(gr, fwname, fuc, ret);
if (ret) if (ret)
......
...@@ -36,7 +36,7 @@ nvkm_acr_load_firmware(const struct nvkm_subdev *subdev, const char *name, ...@@ -36,7 +36,7 @@ nvkm_acr_load_firmware(const struct nvkm_subdev *subdev, const char *name,
void *blob; void *blob;
int ret; int ret;
ret = nvkm_firmware_get(subdev->device, name, &fw); ret = nvkm_firmware_get(subdev, name, &fw);
if (ret) if (ret)
return ERR_PTR(ret); return ERR_PTR(ret);
if (fw->size < min_size) { if (fw->size < min_size) {
......
...@@ -229,6 +229,8 @@ struct acr_r352_lsf_wpr_header { ...@@ -229,6 +229,8 @@ struct acr_r352_lsf_wpr_header {
struct ls_ucode_img_r352 { struct ls_ucode_img_r352 {
struct ls_ucode_img base; struct ls_ucode_img base;
const struct acr_r352_lsf_func *func;
struct acr_r352_lsf_wpr_header wpr_header; struct acr_r352_lsf_wpr_header wpr_header;
struct acr_r352_lsf_lsb_header lsb_header; struct acr_r352_lsf_lsb_header lsb_header;
}; };
...@@ -243,6 +245,7 @@ acr_r352_ls_ucode_img_load(const struct acr_r352 *acr, ...@@ -243,6 +245,7 @@ acr_r352_ls_ucode_img_load(const struct acr_r352 *acr,
enum nvkm_secboot_falcon falcon_id) enum nvkm_secboot_falcon falcon_id)
{ {
const struct nvkm_subdev *subdev = acr->base.subdev; const struct nvkm_subdev *subdev = acr->base.subdev;
const struct acr_r352_ls_func *func = acr->func->ls_func[falcon_id];
struct ls_ucode_img_r352 *img; struct ls_ucode_img_r352 *img;
int ret; int ret;
...@@ -252,15 +255,16 @@ acr_r352_ls_ucode_img_load(const struct acr_r352 *acr, ...@@ -252,15 +255,16 @@ acr_r352_ls_ucode_img_load(const struct acr_r352 *acr,
img->base.falcon_id = falcon_id; img->base.falcon_id = falcon_id;
ret = acr->func->ls_func[falcon_id]->load(sb, &img->base); ret = func->load(sb, func->version_max, &img->base);
if (ret < 0) {
if (ret) {
kfree(img->base.ucode_data); kfree(img->base.ucode_data);
kfree(img->base.sig); kfree(img->base.sig);
kfree(img); kfree(img);
return ERR_PTR(ret); return ERR_PTR(ret);
} }
img->func = func->version[ret];
/* Check that the signature size matches our expectations... */ /* Check that the signature size matches our expectations... */
if (img->base.sig_size != sizeof(img->lsb_header.signature)) { if (img->base.sig_size != sizeof(img->lsb_header.signature)) {
nvkm_error(subdev, "invalid signature size for %s falcon!\n", nvkm_error(subdev, "invalid signature size for %s falcon!\n",
...@@ -302,8 +306,7 @@ acr_r352_ls_img_fill_headers(struct acr_r352 *acr, ...@@ -302,8 +306,7 @@ acr_r352_ls_img_fill_headers(struct acr_r352 *acr,
struct acr_r352_lsf_wpr_header *whdr = &img->wpr_header; struct acr_r352_lsf_wpr_header *whdr = &img->wpr_header;
struct acr_r352_lsf_lsb_header *lhdr = &img->lsb_header; struct acr_r352_lsf_lsb_header *lhdr = &img->lsb_header;
struct ls_ucode_img_desc *desc = &_img->ucode_desc; struct ls_ucode_img_desc *desc = &_img->ucode_desc;
const struct acr_r352_ls_func *func = const struct acr_r352_lsf_func *func = img->func;
acr->func->ls_func[_img->falcon_id];
/* Fill WPR header */ /* Fill WPR header */
whdr->falcon_id = _img->falcon_id; whdr->falcon_id = _img->falcon_id;
...@@ -419,8 +422,8 @@ acr_r352_ls_write_wpr(struct acr_r352 *acr, struct list_head *imgs, ...@@ -419,8 +422,8 @@ acr_r352_ls_write_wpr(struct acr_r352 *acr, struct list_head *imgs,
/* Figure out how large we need gdesc to be. */ /* Figure out how large we need gdesc to be. */
list_for_each_entry(_img, imgs, node) { list_for_each_entry(_img, imgs, node) {
const struct acr_r352_ls_func *ls_func = struct ls_ucode_img_r352 *img = ls_ucode_img_r352(_img);
acr->func->ls_func[_img->falcon_id]; const struct acr_r352_lsf_func *ls_func = img->func;
max_desc_size = max(max_desc_size, ls_func->bl_desc_size); max_desc_size = max(max_desc_size, ls_func->bl_desc_size);
} }
...@@ -433,8 +436,7 @@ acr_r352_ls_write_wpr(struct acr_r352 *acr, struct list_head *imgs, ...@@ -433,8 +436,7 @@ acr_r352_ls_write_wpr(struct acr_r352 *acr, struct list_head *imgs,
list_for_each_entry(_img, imgs, node) { list_for_each_entry(_img, imgs, node) {
struct ls_ucode_img_r352 *img = ls_ucode_img_r352(_img); struct ls_ucode_img_r352 *img = ls_ucode_img_r352(_img);
const struct acr_r352_ls_func *ls_func = const struct acr_r352_lsf_func *ls_func = img->func;
acr->func->ls_func[_img->falcon_id];
nvkm_gpuobj_memcpy_to(wpr_blob, pos, &img->wpr_header, nvkm_gpuobj_memcpy_to(wpr_blob, pos, &img->wpr_header,
sizeof(img->wpr_header)); sizeof(img->wpr_header));
...@@ -1063,20 +1065,36 @@ acr_r352_dtor(struct nvkm_acr *_acr) ...@@ -1063,20 +1065,36 @@ acr_r352_dtor(struct nvkm_acr *_acr)
kfree(acr); kfree(acr);
} }
static const struct acr_r352_lsf_func
acr_r352_ls_fecs_func_0 = {
.generate_bl_desc = acr_r352_generate_flcn_bl_desc,
.bl_desc_size = sizeof(struct acr_r352_flcn_bl_desc),
};
const struct acr_r352_ls_func const struct acr_r352_ls_func
acr_r352_ls_fecs_func = { acr_r352_ls_fecs_func = {
.load = acr_ls_ucode_load_fecs, .load = acr_ls_ucode_load_fecs,
.version_max = 0,
.version = {
&acr_r352_ls_fecs_func_0,
}
};
static const struct acr_r352_lsf_func
acr_r352_ls_gpccs_func_0 = {
.generate_bl_desc = acr_r352_generate_flcn_bl_desc, .generate_bl_desc = acr_r352_generate_flcn_bl_desc,
.bl_desc_size = sizeof(struct acr_r352_flcn_bl_desc), .bl_desc_size = sizeof(struct acr_r352_flcn_bl_desc),
/* GPCCS will be loaded using PRI */
.lhdr_flags = LSF_FLAG_FORCE_PRIV_LOAD,
}; };
const struct acr_r352_ls_func const struct acr_r352_ls_func
acr_r352_ls_gpccs_func = { acr_r352_ls_gpccs_func = {
.load = acr_ls_ucode_load_gpccs, .load = acr_ls_ucode_load_gpccs,
.generate_bl_desc = acr_r352_generate_flcn_bl_desc, .version_max = 0,
.bl_desc_size = sizeof(struct acr_r352_flcn_bl_desc), .version = {
/* GPCCS will be loaded using PRI */ &acr_r352_ls_gpccs_func_0,
.lhdr_flags = LSF_FLAG_FORCE_PRIV_LOAD, }
}; };
...@@ -1150,12 +1168,20 @@ acr_r352_generate_pmu_bl_desc(const struct nvkm_acr *acr, ...@@ -1150,12 +1168,20 @@ acr_r352_generate_pmu_bl_desc(const struct nvkm_acr *acr,
desc->argv = addr_args; desc->argv = addr_args;
} }
static const struct acr_r352_lsf_func
acr_r352_ls_pmu_func_0 = {
.generate_bl_desc = acr_r352_generate_pmu_bl_desc,
.bl_desc_size = sizeof(struct acr_r352_pmu_bl_desc),
};
static const struct acr_r352_ls_func static const struct acr_r352_ls_func
acr_r352_ls_pmu_func = { acr_r352_ls_pmu_func = {
.load = acr_ls_ucode_load_pmu, .load = acr_ls_ucode_load_pmu,
.generate_bl_desc = acr_r352_generate_pmu_bl_desc,
.bl_desc_size = sizeof(struct acr_r352_pmu_bl_desc),
.post_run = acr_ls_pmu_post_run, .post_run = acr_ls_pmu_post_run,
.version_max = 0,
.version = {
&acr_r352_ls_pmu_func_0,
}
}; };
const struct acr_r352_func const struct acr_r352_func
......
...@@ -47,24 +47,34 @@ hsf_load_header_app_size(const struct hsf_load_header *hdr, u32 app) ...@@ -47,24 +47,34 @@ hsf_load_header_app_size(const struct hsf_load_header *hdr, u32 app)
} }
/** /**
* struct acr_r352_ls_func - manages a single LS firmware * struct acr_r352_lsf_func - manages a specific LS firmware version
* *
* @load: load the external firmware into a ls_ucode_img
* @generate_bl_desc: function called on a block of bl_desc_size to generate the * @generate_bl_desc: function called on a block of bl_desc_size to generate the
* proper bootloader descriptor for this LS firmware * proper bootloader descriptor for this LS firmware
* @bl_desc_size: size of the bootloader descriptor * @bl_desc_size: size of the bootloader descriptor
* @post_run: hook called right after the ACR is executed
* @lhdr_flags: LS flags * @lhdr_flags: LS flags
*/ */
struct acr_r352_ls_func { struct acr_r352_lsf_func {
int (*load)(const struct nvkm_secboot *, struct ls_ucode_img *);
void (*generate_bl_desc)(const struct nvkm_acr *, void (*generate_bl_desc)(const struct nvkm_acr *,
const struct ls_ucode_img *, u64, void *); const struct ls_ucode_img *, u64, void *);
u32 bl_desc_size; u32 bl_desc_size;
int (*post_run)(const struct nvkm_acr *, const struct nvkm_secboot *);
u32 lhdr_flags; u32 lhdr_flags;
}; };
/**
* struct acr_r352_ls_func - manages a single LS falcon
*
* @load: load the external firmware into a ls_ucode_img
* @post_run: hook called right after the ACR is executed
*/
struct acr_r352_ls_func {
int (*load)(const struct nvkm_secboot *, int maxver,
struct ls_ucode_img *);
int (*post_run)(const struct nvkm_acr *, const struct nvkm_secboot *);
int version_max;
const struct acr_r352_lsf_func *version[];
};
struct acr_r352; struct acr_r352;
/** /**
......
...@@ -66,20 +66,36 @@ acr_r361_generate_hs_bl_desc(const struct hsf_load_header *hdr, void *_bl_desc, ...@@ -66,20 +66,36 @@ acr_r361_generate_hs_bl_desc(const struct hsf_load_header *hdr, void *_bl_desc,
bl_desc->data_size = hdr->data_size; bl_desc->data_size = hdr->data_size;
} }
static const struct acr_r352_lsf_func
acr_r361_ls_fecs_func_0 = {
.generate_bl_desc = acr_r361_generate_flcn_bl_desc,
.bl_desc_size = sizeof(struct acr_r361_flcn_bl_desc),
};
const struct acr_r352_ls_func const struct acr_r352_ls_func
acr_r361_ls_fecs_func = { acr_r361_ls_fecs_func = {
.load = acr_ls_ucode_load_fecs, .load = acr_ls_ucode_load_fecs,
.version_max = 0,
.version = {
&acr_r361_ls_fecs_func_0,
}
};
static const struct acr_r352_lsf_func
acr_r361_ls_gpccs_func_0 = {
.generate_bl_desc = acr_r361_generate_flcn_bl_desc, .generate_bl_desc = acr_r361_generate_flcn_bl_desc,
.bl_desc_size = sizeof(struct acr_r361_flcn_bl_desc), .bl_desc_size = sizeof(struct acr_r361_flcn_bl_desc),
/* GPCCS will be loaded using PRI */
.lhdr_flags = LSF_FLAG_FORCE_PRIV_LOAD,
}; };
const struct acr_r352_ls_func const struct acr_r352_ls_func
acr_r361_ls_gpccs_func = { acr_r361_ls_gpccs_func = {
.load = acr_ls_ucode_load_gpccs, .load = acr_ls_ucode_load_gpccs,
.generate_bl_desc = acr_r361_generate_flcn_bl_desc, .version_max = 0,
.bl_desc_size = sizeof(struct acr_r361_flcn_bl_desc), .version = {
/* GPCCS will be loaded using PRI */ &acr_r361_ls_gpccs_func_0,
.lhdr_flags = LSF_FLAG_FORCE_PRIV_LOAD, }
}; };
struct acr_r361_pmu_bl_desc { struct acr_r361_pmu_bl_desc {
...@@ -125,12 +141,20 @@ acr_r361_generate_pmu_bl_desc(const struct nvkm_acr *acr, ...@@ -125,12 +141,20 @@ acr_r361_generate_pmu_bl_desc(const struct nvkm_acr *acr,
desc->argv = addr_args; desc->argv = addr_args;
} }
static const struct acr_r352_lsf_func
acr_r361_ls_pmu_func_0 = {
.generate_bl_desc = acr_r361_generate_pmu_bl_desc,
.bl_desc_size = sizeof(struct acr_r361_pmu_bl_desc),
};
const struct acr_r352_ls_func const struct acr_r352_ls_func
acr_r361_ls_pmu_func = { acr_r361_ls_pmu_func = {
.load = acr_ls_ucode_load_pmu, .load = acr_ls_ucode_load_pmu,
.generate_bl_desc = acr_r361_generate_pmu_bl_desc,
.bl_desc_size = sizeof(struct acr_r361_pmu_bl_desc),
.post_run = acr_ls_pmu_post_run, .post_run = acr_ls_pmu_post_run,
.version_max = 0,
.version = {
&acr_r361_ls_pmu_func_0,
}
}; };
static void static void
...@@ -164,12 +188,20 @@ acr_r361_generate_sec2_bl_desc(const struct nvkm_acr *acr, ...@@ -164,12 +188,20 @@ acr_r361_generate_sec2_bl_desc(const struct nvkm_acr *acr,
desc->argv = 0x01000000; desc->argv = 0x01000000;
} }
const struct acr_r352_ls_func const struct acr_r352_lsf_func
acr_r361_ls_sec2_func = { acr_r361_ls_sec2_func_0 = {
.load = acr_ls_ucode_load_sec2,
.generate_bl_desc = acr_r361_generate_sec2_bl_desc, .generate_bl_desc = acr_r361_generate_sec2_bl_desc,
.bl_desc_size = sizeof(struct acr_r361_pmu_bl_desc), .bl_desc_size = sizeof(struct acr_r361_pmu_bl_desc),
};
static const struct acr_r352_ls_func
acr_r361_ls_sec2_func = {
.load = acr_ls_ucode_load_sec2,
.post_run = acr_ls_sec2_post_run, .post_run = acr_ls_sec2_post_run,
.version_max = 0,
.version = {
&acr_r361_ls_sec2_func_0,
}
}; };
......
...@@ -67,6 +67,5 @@ void acr_r361_generate_hs_bl_desc(const struct hsf_load_header *, void *, u64); ...@@ -67,6 +67,5 @@ void acr_r361_generate_hs_bl_desc(const struct hsf_load_header *, void *, u64);
extern const struct acr_r352_ls_func acr_r361_ls_fecs_func; extern const struct acr_r352_ls_func acr_r361_ls_fecs_func;
extern const struct acr_r352_ls_func acr_r361_ls_gpccs_func; extern const struct acr_r352_ls_func acr_r361_ls_gpccs_func;
extern const struct acr_r352_ls_func acr_r361_ls_pmu_func; extern const struct acr_r352_ls_func acr_r361_ls_pmu_func;
extern const struct acr_r352_ls_func acr_r361_ls_sec2_func; extern const struct acr_r352_lsf_func acr_r361_ls_sec2_func_0;
#endif #endif
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "acr_r367.h" #include "acr_r367.h"
#include "acr_r361.h" #include "acr_r361.h"
#include "acr_r370.h"
#include <core/gpuobj.h> #include <core/gpuobj.h>
...@@ -100,6 +101,8 @@ struct acr_r367_lsf_wpr_header { ...@@ -100,6 +101,8 @@ struct acr_r367_lsf_wpr_header {
struct ls_ucode_img_r367 { struct ls_ucode_img_r367 {
struct ls_ucode_img base; struct ls_ucode_img base;
const struct acr_r352_lsf_func *func;
struct acr_r367_lsf_wpr_header wpr_header; struct acr_r367_lsf_wpr_header wpr_header;
struct acr_r367_lsf_lsb_header lsb_header; struct acr_r367_lsf_lsb_header lsb_header;
}; };
...@@ -111,6 +114,7 @@ acr_r367_ls_ucode_img_load(const struct acr_r352 *acr, ...@@ -111,6 +114,7 @@ acr_r367_ls_ucode_img_load(const struct acr_r352 *acr,
enum nvkm_secboot_falcon falcon_id) enum nvkm_secboot_falcon falcon_id)
{ {
const struct nvkm_subdev *subdev = acr->base.subdev; const struct nvkm_subdev *subdev = acr->base.subdev;
const struct acr_r352_ls_func *func = acr->func->ls_func[falcon_id];
struct ls_ucode_img_r367 *img; struct ls_ucode_img_r367 *img;
int ret; int ret;
...@@ -120,14 +124,16 @@ acr_r367_ls_ucode_img_load(const struct acr_r352 *acr, ...@@ -120,14 +124,16 @@ acr_r367_ls_ucode_img_load(const struct acr_r352 *acr,
img->base.falcon_id = falcon_id; img->base.falcon_id = falcon_id;
ret = acr->func->ls_func[falcon_id]->load(sb, &img->base); ret = func->load(sb, func->version_max, &img->base);
if (ret) { if (ret < 0) {
kfree(img->base.ucode_data); kfree(img->base.ucode_data);
kfree(img->base.sig); kfree(img->base.sig);
kfree(img); kfree(img);
return ERR_PTR(ret); return ERR_PTR(ret);
} }
img->func = func->version[ret];
/* Check that the signature size matches our expectations... */ /* Check that the signature size matches our expectations... */
if (img->base.sig_size != sizeof(img->lsb_header.signature)) { if (img->base.sig_size != sizeof(img->lsb_header.signature)) {
nvkm_error(subdev, "invalid signature size for %s falcon!\n", nvkm_error(subdev, "invalid signature size for %s falcon!\n",
...@@ -158,8 +164,7 @@ acr_r367_ls_img_fill_headers(struct acr_r352 *acr, ...@@ -158,8 +164,7 @@ acr_r367_ls_img_fill_headers(struct acr_r352 *acr,
struct acr_r367_lsf_wpr_header *whdr = &img->wpr_header; struct acr_r367_lsf_wpr_header *whdr = &img->wpr_header;
struct acr_r367_lsf_lsb_header *lhdr = &img->lsb_header; struct acr_r367_lsf_lsb_header *lhdr = &img->lsb_header;
struct ls_ucode_img_desc *desc = &_img->ucode_desc; struct ls_ucode_img_desc *desc = &_img->ucode_desc;
const struct acr_r352_ls_func *func = const struct acr_r352_lsf_func *func = img->func;
acr->func->ls_func[_img->falcon_id];
/* Fill WPR header */ /* Fill WPR header */
whdr->falcon_id = _img->falcon_id; whdr->falcon_id = _img->falcon_id;
...@@ -269,8 +274,8 @@ acr_r367_ls_write_wpr(struct acr_r352 *acr, struct list_head *imgs, ...@@ -269,8 +274,8 @@ acr_r367_ls_write_wpr(struct acr_r352 *acr, struct list_head *imgs,
u8 *gdesc; u8 *gdesc;
list_for_each_entry(_img, imgs, node) { list_for_each_entry(_img, imgs, node) {
const struct acr_r352_ls_func *ls_func = struct ls_ucode_img_r367 *img = ls_ucode_img_r367(_img);
acr->func->ls_func[_img->falcon_id]; const struct acr_r352_lsf_func *ls_func = img->func;
max_desc_size = max(max_desc_size, ls_func->bl_desc_size); max_desc_size = max(max_desc_size, ls_func->bl_desc_size);
} }
...@@ -283,8 +288,7 @@ acr_r367_ls_write_wpr(struct acr_r352 *acr, struct list_head *imgs, ...@@ -283,8 +288,7 @@ acr_r367_ls_write_wpr(struct acr_r352 *acr, struct list_head *imgs,
list_for_each_entry(_img, imgs, node) { list_for_each_entry(_img, imgs, node) {
struct ls_ucode_img_r367 *img = ls_ucode_img_r367(_img); struct ls_ucode_img_r367 *img = ls_ucode_img_r367(_img);
const struct acr_r352_ls_func *ls_func = const struct acr_r352_lsf_func *ls_func = img->func;
acr->func->ls_func[_img->falcon_id];
nvkm_gpuobj_memcpy_to(wpr_blob, pos, &img->wpr_header, nvkm_gpuobj_memcpy_to(wpr_blob, pos, &img->wpr_header,
sizeof(img->wpr_header)); sizeof(img->wpr_header));
...@@ -378,6 +382,17 @@ acr_r367_fixup_hs_desc(struct acr_r352 *acr, struct nvkm_secboot *sb, ...@@ -378,6 +382,17 @@ acr_r367_fixup_hs_desc(struct acr_r352 *acr, struct nvkm_secboot *sb,
} }
} }
static const struct acr_r352_ls_func
acr_r367_ls_sec2_func = {
.load = acr_ls_ucode_load_sec2,
.post_run = acr_ls_sec2_post_run,
.version_max = 1,
.version = {
&acr_r361_ls_sec2_func_0,
&acr_r370_ls_sec2_func_0,
}
};
const struct acr_r352_func const struct acr_r352_func
acr_r367_func = { acr_r367_func = {
.fixup_hs_desc = acr_r367_fixup_hs_desc, .fixup_hs_desc = acr_r367_fixup_hs_desc,
...@@ -391,7 +406,7 @@ acr_r367_func = { ...@@ -391,7 +406,7 @@ acr_r367_func = {
[NVKM_SECBOOT_FALCON_FECS] = &acr_r361_ls_fecs_func, [NVKM_SECBOOT_FALCON_FECS] = &acr_r361_ls_fecs_func,
[NVKM_SECBOOT_FALCON_GPCCS] = &acr_r361_ls_gpccs_func, [NVKM_SECBOOT_FALCON_GPCCS] = &acr_r361_ls_gpccs_func,
[NVKM_SECBOOT_FALCON_PMU] = &acr_r361_ls_pmu_func, [NVKM_SECBOOT_FALCON_PMU] = &acr_r361_ls_pmu_func,
[NVKM_SECBOOT_FALCON_SEC2] = &acr_r361_ls_sec2_func, [NVKM_SECBOOT_FALCON_SEC2] = &acr_r367_ls_sec2_func,
}, },
}; };
......
...@@ -49,20 +49,36 @@ acr_r370_generate_flcn_bl_desc(const struct nvkm_acr *acr, ...@@ -49,20 +49,36 @@ acr_r370_generate_flcn_bl_desc(const struct nvkm_acr *acr,
desc->data_size = pdesc->app_resident_data_size; desc->data_size = pdesc->app_resident_data_size;
} }
static const struct acr_r352_lsf_func
acr_r370_ls_fecs_func_0 = {
.generate_bl_desc = acr_r370_generate_flcn_bl_desc,
.bl_desc_size = sizeof(struct acr_r370_flcn_bl_desc),
};
const struct acr_r352_ls_func const struct acr_r352_ls_func
acr_r370_ls_fecs_func = { acr_r370_ls_fecs_func = {
.load = acr_ls_ucode_load_fecs, .load = acr_ls_ucode_load_fecs,
.version_max = 0,
.version = {
&acr_r370_ls_fecs_func_0,
}
};
static const struct acr_r352_lsf_func
acr_r370_ls_gpccs_func_0 = {
.generate_bl_desc = acr_r370_generate_flcn_bl_desc, .generate_bl_desc = acr_r370_generate_flcn_bl_desc,
.bl_desc_size = sizeof(struct acr_r370_flcn_bl_desc), .bl_desc_size = sizeof(struct acr_r370_flcn_bl_desc),
/* GPCCS will be loaded using PRI */
.lhdr_flags = LSF_FLAG_FORCE_PRIV_LOAD,
}; };
const struct acr_r352_ls_func const struct acr_r352_ls_func
acr_r370_ls_gpccs_func = { acr_r370_ls_gpccs_func = {
.load = acr_ls_ucode_load_gpccs, .load = acr_ls_ucode_load_gpccs,
.generate_bl_desc = acr_r370_generate_flcn_bl_desc, .version_max = 0,
.bl_desc_size = sizeof(struct acr_r370_flcn_bl_desc), .version = {
/* GPCCS will be loaded using PRI */ &acr_r370_ls_gpccs_func_0,
.lhdr_flags = LSF_FLAG_FORCE_PRIV_LOAD, }
}; };
static void static void
...@@ -95,12 +111,20 @@ acr_r370_generate_sec2_bl_desc(const struct nvkm_acr *acr, ...@@ -95,12 +111,20 @@ acr_r370_generate_sec2_bl_desc(const struct nvkm_acr *acr,
desc->argv = 0x01000000; desc->argv = 0x01000000;
} }
const struct acr_r352_lsf_func
acr_r370_ls_sec2_func_0 = {
.generate_bl_desc = acr_r370_generate_sec2_bl_desc,
.bl_desc_size = sizeof(struct acr_r370_flcn_bl_desc),
};
const struct acr_r352_ls_func const struct acr_r352_ls_func
acr_r370_ls_sec2_func = { acr_r370_ls_sec2_func = {
.load = acr_ls_ucode_load_sec2, .load = acr_ls_ucode_load_sec2,
.generate_bl_desc = acr_r370_generate_sec2_bl_desc,
.bl_desc_size = sizeof(struct acr_r370_flcn_bl_desc),
.post_run = acr_ls_sec2_post_run, .post_run = acr_ls_sec2_post_run,
.version_max = 0,
.version = {
&acr_r370_ls_sec2_func_0,
}
}; };
void void
......
...@@ -46,4 +46,5 @@ struct acr_r370_flcn_bl_desc { ...@@ -46,4 +46,5 @@ struct acr_r370_flcn_bl_desc {
void acr_r370_generate_hs_bl_desc(const struct hsf_load_header *, void *, u64); void acr_r370_generate_hs_bl_desc(const struct hsf_load_header *, void *, u64);
extern const struct acr_r352_ls_func acr_r370_ls_fecs_func; extern const struct acr_r352_ls_func acr_r370_ls_fecs_func;
extern const struct acr_r352_ls_func acr_r370_ls_gpccs_func; extern const struct acr_r352_ls_func acr_r370_ls_gpccs_func;
extern const struct acr_r352_lsf_func acr_r370_ls_sec2_func_0;
#endif #endif
...@@ -54,12 +54,20 @@ acr_r375_generate_pmu_bl_desc(const struct nvkm_acr *acr, ...@@ -54,12 +54,20 @@ acr_r375_generate_pmu_bl_desc(const struct nvkm_acr *acr,
desc->argv = addr_args; desc->argv = addr_args;
} }
static const struct acr_r352_lsf_func
acr_r375_ls_pmu_func_0 = {
.generate_bl_desc = acr_r375_generate_pmu_bl_desc,
.bl_desc_size = sizeof(struct acr_r370_flcn_bl_desc),
};
const struct acr_r352_ls_func const struct acr_r352_ls_func
acr_r375_ls_pmu_func = { acr_r375_ls_pmu_func = {
.load = acr_ls_ucode_load_pmu, .load = acr_ls_ucode_load_pmu,
.generate_bl_desc = acr_r375_generate_pmu_bl_desc,
.bl_desc_size = sizeof(struct acr_r370_flcn_bl_desc),
.post_run = acr_ls_pmu_post_run, .post_run = acr_ls_pmu_post_run,
.version_max = 0,
.version = {
&acr_r375_ls_pmu_func_0,
}
}; };
const struct acr_r352_func const struct acr_r352_func
......
...@@ -147,11 +147,15 @@ struct fw_bl_desc { ...@@ -147,11 +147,15 @@ struct fw_bl_desc {
u32 data_size; u32 data_size;
}; };
int acr_ls_ucode_load_fecs(const struct nvkm_secboot *, struct ls_ucode_img *); int acr_ls_ucode_load_fecs(const struct nvkm_secboot *, int,
int acr_ls_ucode_load_gpccs(const struct nvkm_secboot *, struct ls_ucode_img *); struct ls_ucode_img *);
int acr_ls_ucode_load_pmu(const struct nvkm_secboot *, struct ls_ucode_img *); int acr_ls_ucode_load_gpccs(const struct nvkm_secboot *, int,
struct ls_ucode_img *);
int acr_ls_ucode_load_pmu(const struct nvkm_secboot *, int,
struct ls_ucode_img *);
int acr_ls_pmu_post_run(const struct nvkm_acr *, const struct nvkm_secboot *); int acr_ls_pmu_post_run(const struct nvkm_acr *, const struct nvkm_secboot *);
int acr_ls_ucode_load_sec2(const struct nvkm_secboot *, struct ls_ucode_img *); int acr_ls_ucode_load_sec2(const struct nvkm_secboot *, int,
struct ls_ucode_img *);
int acr_ls_sec2_post_run(const struct nvkm_acr *, const struct nvkm_secboot *); int acr_ls_sec2_post_run(const struct nvkm_acr *, const struct nvkm_secboot *);
#endif #endif
...@@ -90,30 +90,30 @@ ls_ucode_img_build(const struct firmware *bl, const struct firmware *code, ...@@ -90,30 +90,30 @@ ls_ucode_img_build(const struct firmware *bl, const struct firmware *code,
* blob. Also generate the corresponding ucode descriptor. * blob. Also generate the corresponding ucode descriptor.
*/ */
static int static int
ls_ucode_img_load_gr(const struct nvkm_subdev *subdev, struct ls_ucode_img *img, ls_ucode_img_load_gr(const struct nvkm_subdev *subdev, int maxver,
const char *falcon_name) struct ls_ucode_img *img, const char *falcon_name)
{ {
const struct firmware *bl, *code, *data, *sig; const struct firmware *bl, *code, *data, *sig;
char f[64]; char f[64];
int ret; int ret;
snprintf(f, sizeof(f), "gr/%s_bl", falcon_name); snprintf(f, sizeof(f), "gr/%s_bl", falcon_name);
ret = nvkm_firmware_get(subdev->device, f, &bl); ret = nvkm_firmware_get(subdev, f, &bl);
if (ret) if (ret)
goto error; goto error;
snprintf(f, sizeof(f), "gr/%s_inst", falcon_name); snprintf(f, sizeof(f), "gr/%s_inst", falcon_name);
ret = nvkm_firmware_get(subdev->device, f, &code); ret = nvkm_firmware_get(subdev, f, &code);
if (ret) if (ret)
goto free_bl; goto free_bl;
snprintf(f, sizeof(f), "gr/%s_data", falcon_name); snprintf(f, sizeof(f), "gr/%s_data", falcon_name);
ret = nvkm_firmware_get(subdev->device, f, &data); ret = nvkm_firmware_get(subdev, f, &data);
if (ret) if (ret)
goto free_inst; goto free_inst;
snprintf(f, sizeof(f), "gr/%s_sig", falcon_name); snprintf(f, sizeof(f), "gr/%s_sig", falcon_name);
ret = nvkm_firmware_get(subdev->device, f, &sig); ret = nvkm_firmware_get(subdev, f, &sig);
if (ret) if (ret)
goto free_data; goto free_data;
...@@ -146,13 +146,15 @@ ls_ucode_img_load_gr(const struct nvkm_subdev *subdev, struct ls_ucode_img *img, ...@@ -146,13 +146,15 @@ ls_ucode_img_load_gr(const struct nvkm_subdev *subdev, struct ls_ucode_img *img,
} }
int int
acr_ls_ucode_load_fecs(const struct nvkm_secboot *sb, struct ls_ucode_img *img) acr_ls_ucode_load_fecs(const struct nvkm_secboot *sb, int maxver,
struct ls_ucode_img *img)
{ {
return ls_ucode_img_load_gr(&sb->subdev, img, "fecs"); return ls_ucode_img_load_gr(&sb->subdev, maxver, img, "fecs");
} }
int int
acr_ls_ucode_load_gpccs(const struct nvkm_secboot *sb, struct ls_ucode_img *img) acr_ls_ucode_load_gpccs(const struct nvkm_secboot *sb, int maxver,
struct ls_ucode_img *img)
{ {
return ls_ucode_img_load_gr(&sb->subdev, img, "gpccs"); return ls_ucode_img_load_gr(&sb->subdev, maxver, img, "gpccs");
} }
...@@ -39,32 +39,32 @@ ...@@ -39,32 +39,32 @@
*/ */
static int static int
acr_ls_ucode_load_msgqueue(const struct nvkm_subdev *subdev, const char *name, acr_ls_ucode_load_msgqueue(const struct nvkm_subdev *subdev, const char *name,
struct ls_ucode_img *img) int maxver, struct ls_ucode_img *img)
{ {
const struct firmware *image, *desc, *sig; const struct firmware *image, *desc, *sig;
char f[64]; char f[64];
int ret; int ver, ret;
snprintf(f, sizeof(f), "%s/image", name); snprintf(f, sizeof(f), "%s/image", name);
ret = nvkm_firmware_get(subdev->device, f, &image); ver = nvkm_firmware_get_version(subdev, f, 0, maxver, &image);
if (ret) if (ver < 0)
return ret; return ver;
img->ucode_data = kmemdup(image->data, image->size, GFP_KERNEL); img->ucode_data = kmemdup(image->data, image->size, GFP_KERNEL);
nvkm_firmware_put(image); nvkm_firmware_put(image);
if (!img->ucode_data) if (!img->ucode_data)
return -ENOMEM; return -ENOMEM;
snprintf(f, sizeof(f), "%s/desc", name); snprintf(f, sizeof(f), "%s/desc", name);
ret = nvkm_firmware_get(subdev->device, f, &desc); ret = nvkm_firmware_get_version(subdev, f, ver, ver, &desc);
if (ret) if (ret < 0)
return ret; return ret;
memcpy(&img->ucode_desc, desc->data, sizeof(img->ucode_desc)); memcpy(&img->ucode_desc, desc->data, sizeof(img->ucode_desc));
img->ucode_size = ALIGN(img->ucode_desc.app_start_offset + img->ucode_desc.app_size, 256); img->ucode_size = ALIGN(img->ucode_desc.app_start_offset + img->ucode_desc.app_size, 256);
nvkm_firmware_put(desc); nvkm_firmware_put(desc);
snprintf(f, sizeof(f), "%s/sig", name); snprintf(f, sizeof(f), "%s/sig", name);
ret = nvkm_firmware_get(subdev->device, f, &sig); ret = nvkm_firmware_get_version(subdev, f, ver, ver, &sig);
if (ret) if (ret < 0)
return ret; return ret;
img->sig_size = sig->size; img->sig_size = sig->size;
img->sig = kmemdup(sig->data, sig->size, GFP_KERNEL); img->sig = kmemdup(sig->data, sig->size, GFP_KERNEL);
...@@ -72,7 +72,7 @@ acr_ls_ucode_load_msgqueue(const struct nvkm_subdev *subdev, const char *name, ...@@ -72,7 +72,7 @@ acr_ls_ucode_load_msgqueue(const struct nvkm_subdev *subdev, const char *name,
if (!img->sig) if (!img->sig)
return -ENOMEM; return -ENOMEM;
return 0; return ver;
} }
static int static int
...@@ -99,12 +99,13 @@ acr_ls_msgqueue_post_run(struct nvkm_msgqueue *queue, ...@@ -99,12 +99,13 @@ acr_ls_msgqueue_post_run(struct nvkm_msgqueue *queue,
} }
int int
acr_ls_ucode_load_pmu(const struct nvkm_secboot *sb, struct ls_ucode_img *img) acr_ls_ucode_load_pmu(const struct nvkm_secboot *sb, int maxver,
struct ls_ucode_img *img)
{ {
struct nvkm_pmu *pmu = sb->subdev.device->pmu; struct nvkm_pmu *pmu = sb->subdev.device->pmu;
int ret; int ret;
ret = acr_ls_ucode_load_msgqueue(&sb->subdev, "pmu", img); ret = acr_ls_ucode_load_msgqueue(&sb->subdev, "pmu", maxver, img);
if (ret) if (ret)
return ret; return ret;
...@@ -136,14 +137,15 @@ acr_ls_pmu_post_run(const struct nvkm_acr *acr, const struct nvkm_secboot *sb) ...@@ -136,14 +137,15 @@ acr_ls_pmu_post_run(const struct nvkm_acr *acr, const struct nvkm_secboot *sb)
} }
int int
acr_ls_ucode_load_sec2(const struct nvkm_secboot *sb, struct ls_ucode_img *img) acr_ls_ucode_load_sec2(const struct nvkm_secboot *sb, int maxver,
struct ls_ucode_img *img)
{ {
struct nvkm_sec2 *sec = sb->subdev.device->sec2; struct nvkm_sec2 *sec = sb->subdev.device->sec2;
int ret; int ver, ret;
ret = acr_ls_ucode_load_msgqueue(&sb->subdev, "sec2", img); ver = acr_ls_ucode_load_msgqueue(&sb->subdev, "sec2", maxver, img);
if (ret) if (ver < 0)
return ret; return ver;
/* Allocate the PMU queue corresponding to the FW version */ /* Allocate the PMU queue corresponding to the FW version */
ret = nvkm_msgqueue_new(img->ucode_desc.app_version, sec->falcon, ret = nvkm_msgqueue_new(img->ucode_desc.app_version, sec->falcon,
...@@ -151,7 +153,7 @@ acr_ls_ucode_load_sec2(const struct nvkm_secboot *sb, struct ls_ucode_img *img) ...@@ -151,7 +153,7 @@ acr_ls_ucode_load_sec2(const struct nvkm_secboot *sb, struct ls_ucode_img *img)
if (ret) if (ret)
return ret; return ret;
return 0; return ver;
} }
int int
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment