diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h index 5d9c3a966de64450f631842327b48b74fb2732b8..836d8b93282296718f120df97ef2a60070db1d5e 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 a2a9a8418777148418dcf0eb3a407bd7c2d8b82d..36b31bf7bc62d6cb3309eb1293b3e0f7af7d8e00 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 51a669e7bf6a9301495c44a0267b060d344226bd..c962df9910dd46a71658a23ce7cb6b586392ed12 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 3a0cca3d3c3b094829ff8f561377785e4facab8d..cf91fd322c98403d018234b8bbcddc4905febc7f 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 fdfb1470587a0f1c16267bffcc5f82458b77d710..9a4aca2ad831c84d4d83b58f4d79c2dcf5a0cb93 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, };