From ebd83762367a5f49183f2e9d8713265148f255ee Mon Sep 17 00:00:00 2001
From: Ben Skeggs <bskeggs@redhat.com>
Date: Tue, 16 Jun 2020 14:57:31 +1000
Subject: drm/nouveau/acr: store a mask of LS falcons the controlling LSFW can
Git-commit: de088372da017df35f6545516815ee012ec92ff6
Patch-mainline: v5.9-rc1
References: jsc#SLE-12680, jsc#SLE-12880, jsc#SLE-12882, jsc#SLE-12883, jsc#SLE-13496, jsc#SLE-15322
bootstrap
This will prevent some pain with broken firmware trees, as under some
circumstances the HSFW can fail and leave the GPU in a state we don't
know how to recover from.
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Signed-off-by: Patrik Jakobsson <pjakobsson@suse.de>
---
.../gpu/drm/nouveau/include/nvkm/subdev/acr.h | 3 ++
.../gpu/drm/nouveau/nvkm/engine/sec2/gp102.c | 6 ++++
.../gpu/drm/nouveau/nvkm/subdev/acr/base.c | 29 +++++++++++++++----
.../gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c | 3 ++
.../gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c | 3 ++
5 files changed, 38 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h
index 5d9c3a966de6..836d8b932822 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h
@@ -39,6 +39,8 @@ struct nvkm_acr {
struct list_head hsfw, hsf;
struct list_head lsfw, lsf;
+ u64 managed_falcons;
+
struct nvkm_memory *wpr;
u64 wpr_start;
u64 wpr_end;
@@ -107,6 +109,7 @@ struct nvkm_acr_lsf_func {
void (*bld_write)(struct nvkm_acr *, u32 bld, struct nvkm_acr_lsfw *);
void (*bld_patch)(struct nvkm_acr *, u32 bld, s64 adjust);
int (*boot)(struct nvkm_falcon *);
+ u64 bootstrap_falcons;
int (*bootstrap_falcon)(struct nvkm_falcon *, enum nvkm_acr_lsf_id);
int (*bootstrap_multiple_falcons)(struct nvkm_falcon *, u32 mask);
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c
index a2a9a8418777..36b31bf7bc62 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c
@@ -115,6 +115,9 @@ gp102_sec2_acr_0 = {
.bld_write = gp102_sec2_acr_bld_write,
.bld_patch = gp102_sec2_acr_bld_patch,
.boot = gp102_sec2_acr_boot,
+ .bootstrap_falcons = BIT_ULL(NVKM_ACR_LSF_FECS) |
+ BIT_ULL(NVKM_ACR_LSF_GPCCS) |
+ BIT_ULL(NVKM_ACR_LSF_SEC2),
.bootstrap_falcon = gp102_sec2_acr_bootstrap_falcon,
};
@@ -294,6 +297,9 @@ gp102_sec2_acr_1 = {
.bld_write = gp102_sec2_acr_bld_write_1,
.bld_patch = gp102_sec2_acr_bld_patch_1,
.boot = gp102_sec2_acr_boot,
+ .bootstrap_falcons = BIT_ULL(NVKM_ACR_LSF_FECS) |
+ BIT_ULL(NVKM_ACR_LSF_GPCCS) |
+ BIT_ULL(NVKM_ACR_LSF_SEC2),
.bootstrap_falcon = gp102_sec2_acr_bootstrap_falcon,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c
index 51a669e7bf6a..c962df9910dd 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c
@@ -156,6 +156,9 @@ nvkm_acr_bootstrap_falcons(struct nvkm_device *device, unsigned long mask)
return -ENOSYS;
}
+ if ((mask & acrflcn->func->bootstrap_falcons) != mask)
+ return -ENOSYS;
+
if (acrflcn->func->bootstrap_multiple_falcons) {
return acrflcn->func->
bootstrap_multiple_falcons(acrflcn->falcon, mask);
@@ -174,13 +177,10 @@ bool
nvkm_acr_managed_falcon(struct nvkm_device *device, enum nvkm_acr_lsf_id id)
{
struct nvkm_acr *acr = device->acr;
- struct nvkm_acr_lsf *lsf;
if (acr) {
- list_for_each_entry(lsf, &acr->lsf, head) {
- if (lsf->id == id)
- return true;
- }
+ if (acr->managed_falcons & BIT_ULL(id))
+ return true;
}
return false;
@@ -220,6 +220,7 @@ nvkm_acr_oneinit(struct nvkm_subdev *subdev)
struct nvkm_acr_lsfw *lsfw, *lsft;
struct nvkm_acr_lsf *lsf;
u32 wpr_size = 0;
+ u64 falcons;
int ret, i;
if (list_empty(&acr->hsfw)) {
@@ -255,12 +256,28 @@ nvkm_acr_oneinit(struct nvkm_subdev *subdev)
lsf->falcon = lsfw->falcon;
lsf->id = lsfw->id;
list_add_tail(&lsf->head, &acr->lsf);
+ acr->managed_falcons |= BIT_ULL(lsf->id);
}
/* Ensure the falcon that'll provide ACR functions is booted first. */
lsf = nvkm_acr_falcon(device);
- if (lsf)
+ if (lsf) {
+ falcons = lsf->func->bootstrap_falcons;
list_move(&lsf->head, &acr->lsf);
+ } else {
+ falcons = acr->func->bootstrap_falcons;
+ }
+
+ /* Cull falcons that can't be bootstrapped, or the HSFW can fail to
+ * boot and leave the GPU in a weird state.
+ */
+ list_for_each_entry_safe(lsfw, lsft, &acr->lsfw, head) {
+ if (!(falcons & BIT_ULL(lsfw->id))) {
+ nvkm_warn(subdev, "%s falcon cannot be bootstrapped\n",
+ nvkm_acr_lsf_id(lsfw->id));
+ nvkm_acr_lsfw_del(lsfw);
+ }
+ }
if (!acr->wpr_fw || acr->wpr_comp)
wpr_size = acr->func->wpr_layout(acr);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c
index 3a0cca3d3c3b..cf91fd322c98 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c
@@ -126,6 +126,9 @@ gm20b_pmu_acr = {
.bld_write = gm20b_pmu_acr_bld_write,
.bld_patch = gm20b_pmu_acr_bld_patch,
.boot = gm20b_pmu_acr_boot,
+ .bootstrap_falcons = BIT_ULL(NVKM_ACR_LSF_PMU) |
+ BIT_ULL(NVKM_ACR_LSF_FECS) |
+ BIT_ULL(NVKM_ACR_LSF_GPCCS),
.bootstrap_falcon = gm20b_pmu_acr_bootstrap_falcon,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c
index fdfb1470587a..9a4aca2ad831 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c
@@ -69,6 +69,9 @@ gp10b_pmu_acr = {
.bld_write = gm20b_pmu_acr_bld_write,
.bld_patch = gm20b_pmu_acr_bld_patch,
.boot = gm20b_pmu_acr_boot,
+ .bootstrap_falcons = BIT_ULL(NVKM_ACR_LSF_PMU) |
+ BIT_ULL(NVKM_ACR_LSF_FECS) |
+ BIT_ULL(NVKM_ACR_LSF_GPCCS),
.bootstrap_falcon = gm20b_pmu_acr_bootstrap_falcon,
.bootstrap_multiple_falcons = gp10b_pmu_acr_bootstrap_multiple_falcons,
};
--
2.29.2