drm/nouveau/pmu/gm20b,gp10b: boot RTOS from PMU init
Cleanup before falcon changes. Signed-off-by: Ben Skeggs <bskeggs@redhat.com> Reviewed-by: Lyude Paul <lyude@redhat.com>
This commit is contained in:
parent
ccdc043123
commit
a9d90860c4
@ -16,7 +16,7 @@ enum nvkm_falcon_dmaidx {
|
||||
|
||||
struct nvkm_falcon {
|
||||
const struct nvkm_falcon_func *func;
|
||||
const struct nvkm_subdev *owner;
|
||||
struct nvkm_subdev *owner;
|
||||
const char *name;
|
||||
u32 addr;
|
||||
|
||||
@ -24,7 +24,7 @@ struct nvkm_falcon {
|
||||
struct mutex dmem_mutex;
|
||||
bool oneinit;
|
||||
|
||||
const struct nvkm_subdev *user;
|
||||
struct nvkm_subdev *user;
|
||||
|
||||
u8 version;
|
||||
u8 secret;
|
||||
@ -50,8 +50,8 @@ struct nvkm_falcon {
|
||||
struct nvkm_engine engine;
|
||||
};
|
||||
|
||||
int nvkm_falcon_get(struct nvkm_falcon *, const struct nvkm_subdev *);
|
||||
void nvkm_falcon_put(struct nvkm_falcon *, const struct nvkm_subdev *);
|
||||
int nvkm_falcon_get(struct nvkm_falcon *, struct nvkm_subdev *);
|
||||
void nvkm_falcon_put(struct nvkm_falcon *, struct nvkm_subdev *);
|
||||
|
||||
int nvkm_falcon_new_(const struct nvkm_falcon_func *, struct nvkm_device *,
|
||||
enum nvkm_subdev_type, int inst, bool enable, u32 addr, struct nvkm_engine **);
|
||||
|
@ -50,6 +50,7 @@ struct nvkm_acr {
|
||||
struct nvkm_vmm *vmm;
|
||||
|
||||
bool done;
|
||||
struct nvkm_acr_lsf *rtos;
|
||||
|
||||
const struct firmware *wpr_fw;
|
||||
bool wpr_comp;
|
||||
|
@ -169,7 +169,7 @@ nvkm_falcon_oneinit(struct nvkm_falcon *falcon)
|
||||
}
|
||||
|
||||
void
|
||||
nvkm_falcon_put(struct nvkm_falcon *falcon, const struct nvkm_subdev *user)
|
||||
nvkm_falcon_put(struct nvkm_falcon *falcon, struct nvkm_subdev *user)
|
||||
{
|
||||
if (unlikely(!falcon))
|
||||
return;
|
||||
@ -183,7 +183,7 @@ nvkm_falcon_put(struct nvkm_falcon *falcon, const struct nvkm_subdev *user)
|
||||
}
|
||||
|
||||
int
|
||||
nvkm_falcon_get(struct nvkm_falcon *falcon, const struct nvkm_subdev *user)
|
||||
nvkm_falcon_get(struct nvkm_falcon *falcon, struct nvkm_subdev *user)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
|
@ -63,10 +63,30 @@ nvkm_acr_hsf_boot(struct nvkm_acr *acr, const char *name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct nvkm_acr_lsf *
|
||||
nvkm_acr_rtos(struct nvkm_acr *acr)
|
||||
{
|
||||
struct nvkm_acr_lsf *lsf;
|
||||
|
||||
if (acr) {
|
||||
list_for_each_entry(lsf, &acr->lsf, head) {
|
||||
if (lsf->func->bootstrap_falcon)
|
||||
return lsf;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
nvkm_acr_unload(struct nvkm_acr *acr)
|
||||
{
|
||||
if (acr->done) {
|
||||
if (acr->rtos) {
|
||||
nvkm_subdev_unref(acr->rtos->falcon->owner);
|
||||
acr->rtos = NULL;
|
||||
}
|
||||
|
||||
nvkm_acr_hsf_boot(acr, "unload");
|
||||
acr->done = false;
|
||||
}
|
||||
@ -76,6 +96,7 @@ static int
|
||||
nvkm_acr_load(struct nvkm_acr *acr)
|
||||
{
|
||||
struct nvkm_subdev *subdev = &acr->subdev;
|
||||
struct nvkm_acr_lsf *rtos = nvkm_acr_rtos(acr);
|
||||
struct nvkm_acr_lsf *lsf;
|
||||
u64 start, limit;
|
||||
int ret;
|
||||
@ -100,6 +121,14 @@ nvkm_acr_load(struct nvkm_acr *acr)
|
||||
|
||||
acr->done = true;
|
||||
|
||||
if (rtos) {
|
||||
ret = nvkm_subdev_ref(rtos->falcon->owner);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
acr->rtos = rtos;
|
||||
}
|
||||
|
||||
list_for_each_entry(lsf, &acr->lsf, head) {
|
||||
if (lsf->func->boot) {
|
||||
ret = lsf->func->boot(lsf->falcon);
|
||||
@ -118,33 +147,17 @@ nvkm_acr_reload(struct nvkm_acr *acr)
|
||||
return nvkm_acr_load(acr);
|
||||
}
|
||||
|
||||
static struct nvkm_acr_lsf *
|
||||
nvkm_acr_falcon(struct nvkm_device *device)
|
||||
{
|
||||
struct nvkm_acr *acr = device->acr;
|
||||
struct nvkm_acr_lsf *lsf;
|
||||
|
||||
if (acr) {
|
||||
list_for_each_entry(lsf, &acr->lsf, head) {
|
||||
if (lsf->func->bootstrap_falcon)
|
||||
return lsf;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
nvkm_acr_bootstrap_falcons(struct nvkm_device *device, unsigned long mask)
|
||||
{
|
||||
struct nvkm_acr_lsf *acrflcn = nvkm_acr_falcon(device);
|
||||
struct nvkm_acr *acr = device->acr;
|
||||
struct nvkm_acr_lsf *rtos = nvkm_acr_rtos(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) {
|
||||
if (!rtos) {
|
||||
/* Which isn't possible everywhere... */
|
||||
if ((mask & acr->func->bootstrap_falcons) == mask) {
|
||||
int ret = nvkm_acr_reload(acr);
|
||||
@ -156,16 +169,14 @@ nvkm_acr_bootstrap_falcons(struct nvkm_device *device, unsigned long mask)
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
if ((mask & acrflcn->func->bootstrap_falcons) != mask)
|
||||
if ((mask & rtos->func->bootstrap_falcons) != mask)
|
||||
return -ENOSYS;
|
||||
|
||||
if (acrflcn->func->bootstrap_multiple_falcons) {
|
||||
return acrflcn->func->
|
||||
bootstrap_multiple_falcons(acrflcn->falcon, mask);
|
||||
}
|
||||
if (rtos->func->bootstrap_multiple_falcons)
|
||||
return rtos->func->bootstrap_multiple_falcons(rtos->falcon, mask);
|
||||
|
||||
for_each_set_bit(id, &mask, NVKM_ACR_LSF_NUM) {
|
||||
int ret = acrflcn->func->bootstrap_falcon(acrflcn->falcon, id);
|
||||
int ret = rtos->func->bootstrap_falcon(rtos->falcon, id);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
@ -189,6 +200,9 @@ nvkm_acr_managed_falcon(struct nvkm_device *device, enum nvkm_acr_lsf_id id)
|
||||
static int
|
||||
nvkm_acr_fini(struct nvkm_subdev *subdev, bool suspend)
|
||||
{
|
||||
if (!subdev->use.enabled)
|
||||
return 0;
|
||||
|
||||
nvkm_acr_unload(nvkm_acr(subdev));
|
||||
return 0;
|
||||
}
|
||||
@ -196,10 +210,12 @@ nvkm_acr_fini(struct nvkm_subdev *subdev, bool suspend)
|
||||
static int
|
||||
nvkm_acr_init(struct nvkm_subdev *subdev)
|
||||
{
|
||||
if (!nvkm_acr_falcon(subdev->device))
|
||||
struct nvkm_acr *acr = nvkm_acr(subdev);
|
||||
|
||||
if (!nvkm_acr_rtos(acr))
|
||||
return 0;
|
||||
|
||||
return nvkm_acr_load(nvkm_acr(subdev));
|
||||
return nvkm_acr_load(acr);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -218,7 +234,7 @@ nvkm_acr_oneinit(struct nvkm_subdev *subdev)
|
||||
struct nvkm_acr *acr = nvkm_acr(subdev);
|
||||
struct nvkm_acr_hsfw *hsfw;
|
||||
struct nvkm_acr_lsfw *lsfw, *lsft;
|
||||
struct nvkm_acr_lsf *lsf;
|
||||
struct nvkm_acr_lsf *lsf, *rtos;
|
||||
u32 wpr_size = 0;
|
||||
u64 falcons;
|
||||
int ret, i;
|
||||
@ -260,10 +276,10 @@ nvkm_acr_oneinit(struct nvkm_subdev *subdev)
|
||||
}
|
||||
|
||||
/* Ensure the falcon that'll provide ACR functions is booted first. */
|
||||
lsf = nvkm_acr_falcon(device);
|
||||
if (lsf) {
|
||||
falcons = lsf->func->bootstrap_falcons;
|
||||
list_move(&lsf->head, &acr->lsf);
|
||||
rtos = nvkm_acr_rtos(acr);
|
||||
if (rtos) {
|
||||
falcons = rtos->func->bootstrap_falcons;
|
||||
list_move(&rtos->head, &acr->lsf);
|
||||
} else {
|
||||
falcons = acr->func->bootstrap_falcons;
|
||||
}
|
||||
@ -301,7 +317,7 @@ nvkm_acr_oneinit(struct nvkm_subdev *subdev)
|
||||
nvkm_wobj(acr->wpr, 0, acr->wpr_fw->data, acr->wpr_fw->size);
|
||||
|
||||
if (!acr->wpr_fw || acr->wpr_comp)
|
||||
acr->func->wpr_build(acr, nvkm_acr_falcon(device));
|
||||
acr->func->wpr_build(acr, rtos);
|
||||
acr->func->wpr_patch(acr, (s64)acr->wpr_start - acr->wpr_prev);
|
||||
|
||||
if (acr->wpr_fw && acr->wpr_comp) {
|
||||
|
@ -87,13 +87,6 @@ nvkm_pmu_fini(struct nvkm_subdev *subdev, bool suspend)
|
||||
if (pmu->func->fini)
|
||||
pmu->func->fini(pmu);
|
||||
|
||||
flush_work(&pmu->recv.work);
|
||||
|
||||
reinit_completion(&pmu->wpr_ready);
|
||||
|
||||
nvkm_falcon_cmdq_fini(pmu->lpq);
|
||||
nvkm_falcon_cmdq_fini(pmu->hpq);
|
||||
pmu->initmsg_received = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -62,16 +62,6 @@ gm20b_pmu_acr_bootstrap_falcon(struct nvkm_falcon *falcon,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
gm20b_pmu_acr_boot(struct nvkm_falcon *falcon)
|
||||
{
|
||||
struct nv_pmu_args args = { .secure_mode = true };
|
||||
const u32 addr_args = falcon->data.limit - sizeof(struct nv_pmu_args);
|
||||
nvkm_falcon_load_dmem(falcon, &args, addr_args, sizeof(args), 0);
|
||||
nvkm_falcon_start(falcon);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
gm20b_pmu_acr_bld_patch(struct nvkm_acr *acr, u32 bld, s64 adjust)
|
||||
{
|
||||
@ -125,7 +115,6 @@ gm20b_pmu_acr = {
|
||||
.bld_size = sizeof(struct loader_config),
|
||||
.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),
|
||||
@ -198,8 +187,7 @@ gm20b_pmu_recv(struct nvkm_pmu *pmu)
|
||||
if (!pmu->initmsg_received) {
|
||||
int ret = pmu->func->initmsg(pmu);
|
||||
if (ret) {
|
||||
nvkm_error(&pmu->subdev,
|
||||
"error parsing init message: %d\n", ret);
|
||||
nvkm_error(&pmu->subdev, "error parsing init message: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -209,9 +197,44 @@ gm20b_pmu_recv(struct nvkm_pmu *pmu)
|
||||
nvkm_falcon_msgq_recv(pmu->msgq);
|
||||
}
|
||||
|
||||
static void
|
||||
gm20b_pmu_fini(struct nvkm_pmu *pmu)
|
||||
{
|
||||
/*TODO: shutdown RTOS. */
|
||||
|
||||
flush_work(&pmu->recv.work);
|
||||
nvkm_falcon_cmdq_fini(pmu->lpq);
|
||||
nvkm_falcon_cmdq_fini(pmu->hpq);
|
||||
|
||||
reinit_completion(&pmu->wpr_ready);
|
||||
|
||||
nvkm_falcon_put(&pmu->falcon, &pmu->subdev);
|
||||
}
|
||||
|
||||
static int
|
||||
gm20b_pmu_init(struct nvkm_pmu *pmu)
|
||||
{
|
||||
struct nvkm_falcon *falcon = &pmu->falcon;
|
||||
struct nv_pmu_args args = { .secure_mode = true };
|
||||
u32 addr_args = falcon->data.limit - sizeof(args);
|
||||
int ret;
|
||||
|
||||
ret = nvkm_falcon_get(&pmu->falcon, &pmu->subdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pmu->initmsg_received = false;
|
||||
|
||||
nvkm_falcon_load_dmem(falcon, &args, addr_args, sizeof(args), 0);
|
||||
nvkm_falcon_start(falcon);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct nvkm_pmu_func
|
||||
gm20b_pmu = {
|
||||
.flcn = &gm200_pmu_flcn,
|
||||
.init = gm20b_pmu_init,
|
||||
.fini = gm20b_pmu_fini,
|
||||
.intr = gt215_pmu_intr,
|
||||
.recv = gm20b_pmu_recv,
|
||||
.initmsg = gm20b_pmu_initmsg,
|
||||
|
@ -68,7 +68,6 @@ gp10b_pmu_acr = {
|
||||
.bld_size = sizeof(struct loader_config),
|
||||
.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),
|
||||
|
@ -178,6 +178,7 @@ void
|
||||
gt215_pmu_fini(struct nvkm_pmu *pmu)
|
||||
{
|
||||
nvkm_wr32(pmu->subdev.device, 0x10a014, 0x00000060);
|
||||
flush_work(&pmu->recv.work);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -50,7 +50,6 @@ extern const struct nvkm_falcon_func gm200_pmu_flcn;
|
||||
extern const struct nvkm_pmu_func gm20b_pmu;
|
||||
void gm20b_pmu_acr_bld_patch(struct nvkm_acr *, u32, s64);
|
||||
void gm20b_pmu_acr_bld_write(struct nvkm_acr *, u32, struct nvkm_acr_lsfw *);
|
||||
int gm20b_pmu_acr_boot(struct nvkm_falcon *);
|
||||
int gm20b_pmu_acr_bootstrap_falcon(struct nvkm_falcon *, enum nvkm_acr_lsf_id);
|
||||
|
||||
struct nvkm_pmu_fwif {
|
||||
|
Loading…
x
Reference in New Issue
Block a user