summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/nouveau/nvkm/subdev/acr
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2022-06-01 20:48:33 +1000
committerBen Skeggs <bskeggs@redhat.com>2022-11-09 10:45:21 +1000
commit4b569ded09fdadb0c14f797c8dae4e8bc4bbad9f (patch)
treee2bea303d296501fd20e727bdced6880529f939b /drivers/gpu/drm/nouveau/nvkm/subdev/acr
parenta51c69ee74d195e6d84fe9d48ca55f51d39e1b5b (diff)
drm/nouveau/acr/ga102: initial support
v2. fixup for ga103 early merge Signed-off-by: Ben Skeggs <bskeggs@redhat.com> Signed-off-by: Gourav Samaiya <gsamaiya@nvidia.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/subdev/acr')
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/acr/ga100.c49
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/acr/ga102.c326
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c70
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h13
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/acr/tu102.c2
8 files changed, 464 insertions, 6 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild
index ce6ece75f07e..5731f35b11e1 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild
@@ -8,3 +8,5 @@ nvkm-y += nvkm/subdev/acr/gp108.o
nvkm-y += nvkm/subdev/acr/gv100.o
nvkm-y += nvkm/subdev/acr/gp10b.o
nvkm-y += nvkm/subdev/acr/tu102.o
+nvkm-y += nvkm/subdev/acr/ga100.o
+nvkm-y += nvkm/subdev/acr/ga102.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/ga100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/ga100.c
new file mode 100644
index 000000000000..e3370c1551c0
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/ga100.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2021 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "priv.h"
+
+void
+ga100_acr_wpr_check(struct nvkm_acr *acr, u64 *start, u64 *limit)
+{
+ struct nvkm_device *device = acr->subdev.device;
+
+ *start = (u64)(nvkm_rd32(device, 0x1fa81c) & 0xffffff00) << 8;
+ *limit = (u64)(nvkm_rd32(device, 0x1fa820) & 0xffffff00) << 8;
+ *limit = *limit + 0x20000;
+}
+
+int
+ga100_acr_hsfw_ctor(struct nvkm_acr *acr, const char *bl, const char *fw,
+ const char *name, int ver, const struct nvkm_acr_hsf_fwif *fwif)
+{
+ struct nvkm_acr_hsfw *hsfw;
+
+ if (!(hsfw = kzalloc(sizeof(*hsfw), GFP_KERNEL)))
+ return -ENOMEM;
+
+ hsfw->falcon_id = fwif->falcon_id;
+ hsfw->boot_mbox0 = fwif->boot_mbox0;
+ hsfw->intr_clear = fwif->intr_clear;
+ list_add_tail(&hsfw->head, &acr->hsfw);
+
+ return nvkm_falcon_fw_ctor_hs_v2(fwif->func, name, &acr->subdev, fw, ver, NULL, &hsfw->fw);
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/ga102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/ga102.c
new file mode 100644
index 000000000000..45dcf493e972
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/ga102.c
@@ -0,0 +1,326 @@
+/*
+ * Copyright 2021 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "priv.h"
+
+#include <nvfw/acr.h>
+
+static int
+ga102_acr_wpr_patch(struct nvkm_acr *acr, s64 adjust)
+{
+ struct wpr_header_v2 hdr;
+ struct lsb_header_v2 *lsb;
+ struct nvkm_acr_lsfw *lsfw;
+ u32 offset = 0;
+
+ lsb = kvmalloc(sizeof(*lsb), GFP_KERNEL);
+ if (!lsb)
+ return -ENOMEM;
+
+ do {
+ nvkm_robj(acr->wpr, offset, &hdr, sizeof(hdr));
+ wpr_header_v2_dump(&acr->subdev, &hdr);
+
+ list_for_each_entry(lsfw, &acr->lsfw, head) {
+ if (lsfw->id != hdr.wpr.falcon_id)
+ continue;
+
+ nvkm_robj(acr->wpr, hdr.wpr.lsb_offset, lsb, sizeof(*lsb));
+ lsb_header_v2_dump(&acr->subdev, lsb);
+
+ lsfw->func->bld_patch(acr, lsb->bl_data_off, adjust);
+ break;
+ }
+
+ offset += sizeof(hdr);
+ } while (hdr.wpr.falcon_id != WPR_HEADER_V1_FALCON_ID_INVALID);
+
+ kvfree(lsb);
+ return 0;
+}
+
+static int
+ga102_acr_wpr_build_lsb(struct nvkm_acr *acr, struct nvkm_acr_lsfw *lsfw)
+{
+ struct lsb_header_v2 *hdr;
+ int ret = 0;
+
+ if (WARN_ON(lsfw->sig->size != sizeof(hdr->signature)))
+ return -EINVAL;
+
+ hdr = kvzalloc(sizeof(*hdr), GFP_KERNEL);
+ if (!hdr)
+ return -ENOMEM;
+
+ hdr->hdr.identifier = WPR_GENERIC_HEADER_ID_LSF_LSB_HEADER;
+ hdr->hdr.version = 2;
+ hdr->hdr.size = sizeof(*hdr);
+
+ memcpy(&hdr->signature, lsfw->sig->data, lsfw->sig->size);
+ hdr->ucode_off = lsfw->offset.img;
+ hdr->ucode_size = lsfw->ucode_size;
+ hdr->data_size = lsfw->data_size;
+ hdr->bl_code_size = lsfw->bootloader_size;
+ hdr->bl_imem_off = lsfw->bootloader_imem_offset;
+ hdr->bl_data_off = lsfw->offset.bld;
+ hdr->bl_data_size = lsfw->bl_data_size;
+ hdr->app_code_off = lsfw->app_start_offset + lsfw->app_resident_code_offset;
+ hdr->app_code_size = ALIGN(lsfw->app_resident_code_size, 0x100);
+ hdr->app_data_off = lsfw->app_start_offset + lsfw->app_resident_data_offset;
+ hdr->app_data_size = ALIGN(lsfw->app_resident_data_size, 0x100);
+ hdr->app_imem_offset = lsfw->app_imem_offset;
+ hdr->app_dmem_offset = lsfw->app_dmem_offset;
+ hdr->flags = lsfw->func->flags;
+ hdr->monitor_code_offset = 0;
+ hdr->monitor_data_offset = 0;
+ hdr->manifest_offset = 0;
+
+ if (lsfw->secure_bootloader) {
+ struct nvkm_falcon_fw fw = {
+ .fw.img = hdr->hs_fmc_params.pkc_signature,
+ .fw.name = "LSFW",
+ .func = &(const struct nvkm_falcon_fw_func) {
+ .signature = ga100_flcn_fw_signature,
+ },
+ .sig_size = lsfw->sig_size,
+ .sig_nr = lsfw->sig_nr,
+ .sigs = lsfw->sigs,
+ .fuse_ver = lsfw->fuse_ver,
+ .engine_id = lsfw->engine_id,
+ .ucode_id = lsfw->ucode_id,
+ .falcon = lsfw->falcon,
+
+ };
+
+ ret = nvkm_falcon_get(fw.falcon, &acr->subdev);
+ if (ret == 0) {
+ hdr->hs_fmc_params.hs_fmc = 1;
+ hdr->hs_fmc_params.pkc_algo = 0;
+ hdr->hs_fmc_params.pkc_algo_version = 1;
+ hdr->hs_fmc_params.engid_mask = lsfw->engine_id;
+ hdr->hs_fmc_params.ucode_id = lsfw->ucode_id;
+ hdr->hs_fmc_params.fuse_ver = lsfw->fuse_ver;
+ ret = nvkm_falcon_fw_patch(&fw);
+ nvkm_falcon_put(fw.falcon, &acr->subdev);
+ }
+ }
+
+ nvkm_wobj(acr->wpr, lsfw->offset.lsb, hdr, sizeof(*hdr));
+ kvfree(hdr);
+ return ret;
+}
+
+static int
+ga102_acr_wpr_build(struct nvkm_acr *acr, struct nvkm_acr_lsf *rtos)
+{
+ struct nvkm_acr_lsfw *lsfw;
+ struct wpr_header_v2 hdr;
+ u32 offset = 0;
+ int ret;
+
+ /*XXX: shared sub-WPR headers, fill terminator for now. */
+ nvkm_wo32(acr->wpr, 0x300, (2 << 16) | WPR_GENERIC_HEADER_ID_LSF_SHARED_SUB_WPR);
+ nvkm_wo32(acr->wpr, 0x304, 0x14);
+ nvkm_wo32(acr->wpr, 0x308, 0xffffffff);
+ nvkm_wo32(acr->wpr, 0x30c, 0);
+ nvkm_wo32(acr->wpr, 0x310, 0);
+
+ /* Fill per-LSF structures. */
+ list_for_each_entry(lsfw, &acr->lsfw, head) {
+ struct lsf_signature_v2 *sig = (void *)lsfw->sig->data;
+
+ hdr.hdr.identifier = WPR_GENERIC_HEADER_ID_LSF_WPR_HEADER;
+ hdr.hdr.version = 2;
+ hdr.hdr.size = sizeof(hdr);
+ hdr.wpr.falcon_id = lsfw->id;
+ hdr.wpr.lsb_offset = lsfw->offset.lsb;
+ hdr.wpr.bootstrap_owner = NVKM_ACR_LSF_GSPLITE;
+ hdr.wpr.lazy_bootstrap = 1;
+ hdr.wpr.bin_version = sig->ls_ucode_version;
+ hdr.wpr.status = WPR_HEADER_V1_STATUS_COPY;
+
+ /* Write WPR header. */
+ nvkm_wobj(acr->wpr, offset, &hdr, sizeof(hdr));
+ offset += sizeof(hdr);
+
+ /* Write LSB header. */
+ ret = ga102_acr_wpr_build_lsb(acr, lsfw);
+ if (ret)
+ return ret;
+
+ /* Write ucode image. */
+ nvkm_wobj(acr->wpr, lsfw->offset.img,
+ lsfw->img.data,
+ lsfw->img.size);
+
+ /* Write bootloader data. */
+ lsfw->func->bld_write(acr, lsfw->offset.bld, lsfw);
+ }
+
+ /* Finalise WPR. */
+ hdr.hdr.identifier = WPR_GENERIC_HEADER_ID_LSF_WPR_HEADER;
+ hdr.hdr.version = 2;
+ hdr.hdr.size = sizeof(hdr);
+ hdr.wpr.falcon_id = WPR_HEADER_V1_FALCON_ID_INVALID;
+ nvkm_wobj(acr->wpr, offset, &hdr, sizeof(hdr));
+ return 0;
+}
+
+static u32
+ga102_acr_wpr_layout(struct nvkm_acr *acr)
+{
+ struct nvkm_acr_lsfw *lsfw;
+ u32 wpr = 0;
+
+ wpr += 21 /* MAX_LSF */ * sizeof(struct wpr_header_v2);
+ wpr = ALIGN(wpr, 256);
+
+ wpr += 0x100; /* Shared sub-WPR headers. */
+
+ list_for_each_entry(lsfw, &acr->lsfw, head) {
+ wpr = ALIGN(wpr, 256);
+ lsfw->offset.lsb = wpr;
+ wpr += sizeof(struct lsb_header_v2);
+
+ wpr = ALIGN(wpr, 4096);
+ lsfw->offset.img = wpr;
+ wpr += lsfw->img.size;
+
+ wpr = ALIGN(wpr, 256);
+ lsfw->offset.bld = wpr;
+ lsfw->bl_data_size = ALIGN(lsfw->func->bld_size, 256);
+ wpr += lsfw->bl_data_size;
+ }
+
+ return wpr;
+}
+
+static int
+ga102_acr_wpr_parse(struct nvkm_acr *acr)
+{
+ const struct wpr_header_v2 *hdr = (void *)acr->wpr_fw->data;
+
+ while (hdr->wpr.falcon_id != WPR_HEADER_V1_FALCON_ID_INVALID) {
+ wpr_header_v2_dump(&acr->subdev, hdr);
+ if (!nvkm_acr_lsfw_add(NULL, acr, NULL, (hdr++)->wpr.falcon_id))
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+MODULE_FIRMWARE("nvidia/ga102/acr/ucode_unload.bin");
+MODULE_FIRMWARE("nvidia/ga103/acr/ucode_unload.bin");
+MODULE_FIRMWARE("nvidia/ga104/acr/ucode_unload.bin");
+MODULE_FIRMWARE("nvidia/ga106/acr/ucode_unload.bin");
+MODULE_FIRMWARE("nvidia/ga107/acr/ucode_unload.bin");
+
+static const struct nvkm_acr_hsf_fwif
+ga102_acr_unload_fwif[] = {
+ { 0, ga100_acr_hsfw_ctor, &ga102_flcn_fw, NVKM_ACR_HSF_SEC2 },
+ {}
+};
+
+MODULE_FIRMWARE("nvidia/ga102/acr/ucode_asb.bin");
+MODULE_FIRMWARE("nvidia/ga103/acr/ucode_asb.bin");
+MODULE_FIRMWARE("nvidia/ga104/acr/ucode_asb.bin");
+MODULE_FIRMWARE("nvidia/ga106/acr/ucode_asb.bin");
+MODULE_FIRMWARE("nvidia/ga107/acr/ucode_asb.bin");
+
+static const struct nvkm_acr_hsf_fwif
+ga102_acr_asb_fwif[] = {
+ { 0, ga100_acr_hsfw_ctor, &ga102_flcn_fw, NVKM_ACR_HSF_GSP },
+ {}
+};
+
+static const struct nvkm_falcon_fw_func
+ga102_acr_ahesasc_0 = {
+ .signature = ga100_flcn_fw_signature,
+ .reset = gm200_flcn_fw_reset,
+ .setup = gp102_acr_load_setup,
+ .load = ga102_flcn_fw_load,
+ .boot = ga102_flcn_fw_boot,
+};
+
+MODULE_FIRMWARE("nvidia/ga102/acr/ucode_ahesasc.bin");
+MODULE_FIRMWARE("nvidia/ga103/acr/ucode_ahesasc.bin");
+MODULE_FIRMWARE("nvidia/ga104/acr/ucode_ahesasc.bin");
+MODULE_FIRMWARE("nvidia/ga106/acr/ucode_ahesasc.bin");
+MODULE_FIRMWARE("nvidia/ga107/acr/ucode_ahesasc.bin");
+
+static const struct nvkm_acr_hsf_fwif
+ga102_acr_ahesasc_fwif[] = {
+ { 0, ga100_acr_hsfw_ctor, &ga102_acr_ahesasc_0, NVKM_ACR_HSF_SEC2 },
+ {}
+};
+
+static const struct nvkm_acr_func
+ga102_acr = {
+ .ahesasc = ga102_acr_ahesasc_fwif,
+ .asb = ga102_acr_asb_fwif,
+ .unload = ga102_acr_unload_fwif,
+ .wpr_parse = ga102_acr_wpr_parse,
+ .wpr_layout = ga102_acr_wpr_layout,
+ .wpr_alloc = gp102_acr_wpr_alloc,
+ .wpr_patch = ga102_acr_wpr_patch,
+ .wpr_build = ga102_acr_wpr_build,
+ .wpr_check = ga100_acr_wpr_check,
+ .init = tu102_acr_init,
+};
+
+static int
+ga102_acr_load(struct nvkm_acr *acr, int version,
+ const struct nvkm_acr_fwif *fwif)
+{
+ struct nvkm_subdev *subdev = &acr->subdev;
+ const struct nvkm_acr_hsf_fwif *hsfwif;
+
+ hsfwif = nvkm_firmware_load(subdev, fwif->func->ahesasc, "AcrAHESASC",
+ acr, NULL, "acr/ucode_ahesasc", "AHESASC");
+ if (IS_ERR(hsfwif))
+ return PTR_ERR(hsfwif);
+
+ hsfwif = nvkm_firmware_load(subdev, fwif->func->asb, "AcrASB",
+ acr, NULL, "acr/ucode_asb", "ASB");
+ if (IS_ERR(hsfwif))
+ return PTR_ERR(hsfwif);
+
+ hsfwif = nvkm_firmware_load(subdev, fwif->func->unload, "AcrUnload",
+ acr, NULL, "acr/ucode_unload", "unload");
+ if (IS_ERR(hsfwif))
+ return PTR_ERR(hsfwif);
+
+ return 0;
+}
+
+static const struct nvkm_acr_fwif
+ga102_acr_fwif[] = {
+ { 0, ga102_acr_load, &ga102_acr },
+ { -1, gm200_acr_nofw, &gm200_acr },
+ {}
+};
+
+int
+ga102_acr_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
+ struct nvkm_acr **pacr)
+{
+ return nvkm_acr_new_(ga102_acr_fwif, device, type, inst, pacr);
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c
index 7a11151af3bd..31079c947758 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c
@@ -61,7 +61,7 @@ gm200_acr_wpr_check(struct nvkm_acr *acr, u64 *start, u64 *limit)
*limit = *limit + 0x20000;
}
-void
+int
gm200_acr_wpr_patch(struct nvkm_acr *acr, s64 adjust)
{
struct nvkm_subdev *subdev = &acr->subdev;
@@ -86,6 +86,8 @@ gm200_acr_wpr_patch(struct nvkm_acr *acr, s64 adjust)
}
offset += sizeof(hdr);
} while (hdr.falcon_id != WPR_HEADER_V0_FALCON_ID_INVALID);
+
+ return 0;
}
void
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c
index f4c2d3729feb..084f28449e52 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c
@@ -29,7 +29,7 @@
#include <nvfw/acr.h>
#include <nvfw/flcn.h>
-void
+int
gp102_acr_wpr_patch(struct nvkm_acr *acr, s64 adjust)
{
struct wpr_header_v1 hdr;
@@ -54,6 +54,8 @@ gp102_acr_wpr_patch(struct nvkm_acr *acr, s64 adjust)
offset += sizeof(hdr);
} while (hdr.falcon_id != WPR_HEADER_V1_FALCON_ID_INVALID);
+
+ return 0;
}
int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c
index 9b1cf6711ae9..69a059c648c6 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c
@@ -29,6 +29,7 @@ void
nvkm_acr_lsfw_del(struct nvkm_acr_lsfw *lsfw)
{
nvkm_blob_dtor(&lsfw->img);
+ kfree(lsfw->sigs);
nvkm_firmware_put(lsfw->sig);
list_del(&lsfw->head);
kfree(lsfw);
@@ -177,6 +178,75 @@ nvkm_acr_lsfw_load_sig_image_desc_v1(struct nvkm_subdev *subdev,
}
int
+nvkm_acr_lsfw_load_sig_image_desc_v2(struct nvkm_subdev *subdev,
+ struct nvkm_falcon *falcon,
+ enum nvkm_acr_lsf_id id,
+ const char *path, int ver,
+ const struct nvkm_acr_lsf_func *func)
+{
+ const struct firmware *fw;
+ struct nvkm_acr_lsfw *lsfw;
+ const struct nvfw_ls_desc_v2 *desc;
+ int ret = 0;
+
+ lsfw = nvkm_acr_lsfw_load_sig_image_desc_(subdev, falcon, id, path, ver, func, &fw);
+ if (IS_ERR(lsfw))
+ return PTR_ERR(lsfw);
+
+ desc = nvfw_ls_desc_v2(subdev, fw->data);
+
+ lsfw->secure_bootloader = desc->secure_bootloader;
+ lsfw->bootloader_size = ALIGN(desc->bootloader_size, 256);
+ lsfw->bootloader_imem_offset = desc->bootloader_imem_offset;
+
+ lsfw->app_size = ALIGN(desc->app_size, 256);
+ lsfw->app_start_offset = desc->app_start_offset;
+ lsfw->app_imem_entry = desc->app_imem_entry;
+ lsfw->app_resident_code_offset = desc->app_resident_code_offset;
+ lsfw->app_resident_code_size = desc->app_resident_code_size;
+ lsfw->app_resident_data_offset = desc->app_resident_data_offset;
+ lsfw->app_resident_data_size = desc->app_resident_data_size;
+ lsfw->app_imem_offset = desc->app_imem_offset;
+ lsfw->app_dmem_offset = desc->app_dmem_offset;
+
+ lsfw->ucode_size = ALIGN(lsfw->app_resident_data_offset, 256) + lsfw->bootloader_size;
+ lsfw->data_size = lsfw->app_size + lsfw->bootloader_size - lsfw->ucode_size;
+
+ nvkm_firmware_put(fw);
+
+ if (lsfw->secure_bootloader) {
+ const struct firmware *hsbl;
+ const struct nvfw_ls_hsbl_bin_hdr *hdr;
+ const struct nvfw_ls_hsbl_hdr *hshdr;
+ u32 loc, sig, cnt, *meta;
+
+ ret = nvkm_firmware_load_name(subdev, path, "hs_bl_sig", ver, &hsbl);
+ if (ret)
+ return ret;
+
+ hdr = nvfw_ls_hsbl_bin_hdr(subdev, hsbl->data);
+ hshdr = nvfw_ls_hsbl_hdr(subdev, hsbl->data + hdr->header_offset);
+ meta = (u32 *)(hsbl->data + hshdr->meta_data_offset);
+ loc = *(u32 *)(hsbl->data + hshdr->patch_loc);
+ sig = *(u32 *)(hsbl->data + hshdr->patch_sig);
+ cnt = *(u32 *)(hsbl->data + hshdr->num_sig);
+
+ lsfw->fuse_ver = meta[0];
+ lsfw->engine_id = meta[1];
+ lsfw->ucode_id = meta[2];
+ lsfw->sig_size = hshdr->sig_prod_size / cnt;
+ lsfw->sig_nr = cnt;
+ lsfw->sigs = kmemdup(hsbl->data + hshdr->sig_prod_offset + sig,
+ lsfw->sig_nr * lsfw->sig_size, GFP_KERNEL);
+ nvkm_firmware_put(hsbl);
+ if (!lsfw->sigs)
+ ret = -ENOMEM;
+ }
+
+ return ret;
+}
+
+int
nvkm_acr_lsfw_load_bl_inst_data_sig(struct nvkm_subdev *subdev,
struct nvkm_falcon *falcon,
enum nvkm_acr_lsf_id id,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h
index 66a764e24bc6..4881c8ba3880 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h
@@ -24,7 +24,7 @@ struct nvkm_acr_func {
u32 (*wpr_layout)(struct nvkm_acr *);
int (*wpr_alloc)(struct nvkm_acr *, u32 wpr_size);
int (*wpr_build)(struct nvkm_acr *, struct nvkm_acr_lsf *rtos);
- void (*wpr_patch)(struct nvkm_acr *, s64 adjust);
+ int (*wpr_patch)(struct nvkm_acr *, s64 adjust);
void (*wpr_check)(struct nvkm_acr *, u64 *start, u64 *limit);
int (*init)(struct nvkm_acr *);
void (*fini)(struct nvkm_acr *);
@@ -35,7 +35,7 @@ extern const struct nvkm_acr_func gm200_acr;
int gm200_acr_wpr_parse(struct nvkm_acr *);
u32 gm200_acr_wpr_layout(struct nvkm_acr *);
int gm200_acr_wpr_build(struct nvkm_acr *, struct nvkm_acr_lsf *);
-void gm200_acr_wpr_patch(struct nvkm_acr *, s64);
+int gm200_acr_wpr_patch(struct nvkm_acr *, s64);
void gm200_acr_wpr_check(struct nvkm_acr *, u64 *, u64 *);
void gm200_acr_wpr_build_lsb_tail(struct nvkm_acr_lsfw *,
struct lsb_header_tail *);
@@ -48,7 +48,11 @@ u32 gp102_acr_wpr_layout(struct nvkm_acr *);
int gp102_acr_wpr_alloc(struct nvkm_acr *, u32 wpr_size);
int gp102_acr_wpr_build(struct nvkm_acr *, struct nvkm_acr_lsf *);
int gp102_acr_wpr_build_lsb(struct nvkm_acr *, struct nvkm_acr_lsfw *);
-void gp102_acr_wpr_patch(struct nvkm_acr *, s64);
+int gp102_acr_wpr_patch(struct nvkm_acr *, s64);
+
+int tu102_acr_init(struct nvkm_acr *);
+
+void ga100_acr_wpr_check(struct nvkm_acr *, u64 *, u64 *);
struct nvkm_acr_hsfw {
struct nvkm_falcon_fw fw;
@@ -93,6 +97,9 @@ extern const struct nvkm_falcon_fw_func gp108_acr_load_0;
extern const struct nvkm_falcon_fw_func gp108_acr_hsfw_0;
int gp108_acr_hsfw_load_bld(struct nvkm_falcon_fw *);
+int ga100_acr_hsfw_ctor(struct nvkm_acr *, const char *, const char *, const char *, int,
+ const struct nvkm_acr_hsf_fwif *);
+
int nvkm_acr_new_(const struct nvkm_acr_fwif *, struct nvkm_device *, enum nvkm_subdev_type,
int inst, struct nvkm_acr **);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/tu102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/tu102.c
index ad45f5cb452b..c22d551c0078 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/tu102.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/tu102.c
@@ -29,7 +29,7 @@
#include <nvfw/acr.h>
-static int
+int
tu102_acr_init(struct nvkm_acr *acr)
{
int ret = nvkm_acr_hsfw_boot(acr, "AHESASC");