diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/subdev/acr')
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c | 44 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c | 18 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm20b.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp108.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp10b.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/subdev/acr/tu102.c | 1 |
9 files changed, 63 insertions, 17 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c index e4866a02e457..c962df9910dd 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c @@ -141,14 +141,24 @@ nvkm_acr_bootstrap_falcons(struct nvkm_device *device, unsigned long mask) struct nvkm_acr *acr = device->acr; unsigned long id; + /* If there's no LS FW managing bootstrapping of other LS falcons, + * we depend on the HS firmware being able to do it instead. + */ if (!acrflcn) { - int ret = nvkm_acr_reload(acr); - if (ret) - return ret; + /* Which isn't possible everywhere... */ + if ((mask & acr->func->bootstrap_falcons) == mask) { + int ret = nvkm_acr_reload(acr); + if (ret) + return ret; - return acr->done ? 0 : -EINVAL; + return acr->done ? 0 : -EINVAL; + } + 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); @@ -167,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; @@ -213,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)) { @@ -248,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/acr/gm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c index 9a6394085cf0..cd41b2e6cc87 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c @@ -32,6 +32,17 @@ #include <nvfw/acr.h> #include <nvfw/flcn.h> +const struct nvkm_acr_func +gm200_acr = { +}; + +int +gm200_acr_nofw(struct nvkm_acr *acr, int ver, const struct nvkm_acr_fwif *fwif) +{ + nvkm_warn(&acr->subdev, "firmware unavailable\n"); + return 0; +} + int gm200_acr_init(struct nvkm_acr *acr) { @@ -425,7 +436,7 @@ gm200_acr_load_fwif[] = { }; static const struct nvkm_acr_func -gm200_acr = { +gm200_acr_0 = { .load = gm200_acr_load_fwif, .unload = gm200_acr_unload_fwif, .wpr_parse = gm200_acr_wpr_parse, @@ -435,6 +446,8 @@ gm200_acr = { .wpr_patch = gm200_acr_wpr_patch, .wpr_check = gm200_acr_wpr_check, .init = gm200_acr_init, + .bootstrap_falcons = BIT_ULL(NVKM_ACR_LSF_FECS) | + BIT_ULL(NVKM_ACR_LSF_GPCCS), }; static int @@ -459,7 +472,8 @@ gm200_acr_load(struct nvkm_acr *acr, int ver, const struct nvkm_acr_fwif *fwif) static const struct nvkm_acr_fwif gm200_acr_fwif[] = { - { 0, gm200_acr_load, &gm200_acr }, + { 0, gm200_acr_load, &gm200_acr_0 }, + { -1, gm200_acr_nofw, &gm200_acr }, {} }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm20b.c index 034a6ede70c7..b1ecc58152cc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm20b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm20b.c @@ -123,7 +123,8 @@ gm20b_acr_load(struct nvkm_acr *acr, int ver, const struct nvkm_acr_fwif *fwif) static const struct nvkm_acr_fwif gm20b_acr_fwif[] = { - { 0, gm20b_acr_load, &gm20b_acr }, + { 0, gm20b_acr_load, &gm20b_acr }, + { -1, gm200_acr_nofw, &gm200_acr }, {} }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c index 49e11c46d525..80eb9d8dbc80 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c @@ -270,7 +270,8 @@ gp102_acr_load(struct nvkm_acr *acr, int ver, const struct nvkm_acr_fwif *fwif) static const struct nvkm_acr_fwif gp102_acr_fwif[] = { - { 0, gp102_acr_load, &gp102_acr }, + { 0, gp102_acr_load, &gp102_acr }, + { -1, gm200_acr_nofw, &gm200_acr }, {} }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp108.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp108.c index f10dc9112678..67a7c141004b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp108.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp108.c @@ -100,7 +100,8 @@ gp108_acr = { static const struct nvkm_acr_fwif gp108_acr_fwif[] = { - { 0, gp102_acr_load, &gp108_acr }, + { 0, gp102_acr_load, &gp108_acr }, + { -1, gm200_acr_nofw, &gm200_acr }, {} }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp10b.c index 39de64292a41..8249f0d2d81d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp10b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp10b.c @@ -46,7 +46,8 @@ gp10b_acr = { static const struct nvkm_acr_fwif gp10b_acr_fwif[] = { - { 0, gm20b_acr_load, &gp10b_acr }, + { 0, gm20b_acr_load, &gp10b_acr }, + { -1, gm200_acr_nofw, &gm200_acr }, {} }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c index 07d1830126ab..9b1cf6711ae9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c @@ -60,7 +60,7 @@ nvkm_acr_lsfw_add(const struct nvkm_acr_lsf_func *func, struct nvkm_acr *acr, { struct nvkm_acr_lsfw *lsfw; - if (!acr) + if (!acr || list_empty(&acr->hsfw)) return ERR_PTR(-ENOSYS); lsfw = nvkm_acr_lsfw_get(acr, id); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h index d8ba72806d39..d71af17a169a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h @@ -10,6 +10,7 @@ struct nvkm_acr_fwif { const struct nvkm_acr_func *func; }; +int gm200_acr_nofw(struct nvkm_acr *, int, const struct nvkm_acr_fwif *); int gm20b_acr_load(struct nvkm_acr *, int, const struct nvkm_acr_fwif *); int gp102_acr_load(struct nvkm_acr *, int, const struct nvkm_acr_fwif *); @@ -27,8 +28,10 @@ struct nvkm_acr_func { void (*wpr_check)(struct nvkm_acr *, u64 *start, u64 *limit); int (*init)(struct nvkm_acr *); void (*fini)(struct nvkm_acr *); + u64 bootstrap_falcons; }; +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 *); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/tu102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/tu102.c index d28d8f36ae24..c4981bce9a2b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/tu102.c @@ -219,6 +219,7 @@ tu102_acr_load(struct nvkm_acr *acr, int version, static const struct nvkm_acr_fwif tu102_acr_fwif[] = { { 0, tu102_acr_load, &tu102_acr }, + { -1, gm200_acr_nofw, &gm200_acr }, {} }; |