drm/nouveau/gr/gf100: instantiate and reserve GR falcons

Create instances for the FECS and GPCCS falcons and use the init() and
fini() hooks to reserve them for as long as GR controls them.

Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
Alexandre Courbot 2016-12-13 17:11:30 +09:00 committed by Ben Skeggs
parent 0296b5d985
commit 89cd6e2071
2 changed files with 51 additions and 50 deletions

View File

@ -1391,26 +1391,11 @@ gf100_gr_intr(struct nvkm_gr *base)
}
static void
gf100_gr_init_fw(struct gf100_gr *gr, u32 fuc_base,
gf100_gr_init_fw(struct nvkm_falcon *falcon,
struct gf100_gr_fuc *code, struct gf100_gr_fuc *data)
{
struct nvkm_device *device = gr->base.engine.subdev.device;
int i;
nvkm_wr32(device, fuc_base + 0x01c0, 0x01000000);
for (i = 0; i < data->size / 4; i++)
nvkm_wr32(device, fuc_base + 0x01c4, data->data[i]);
nvkm_wr32(device, fuc_base + 0x0180, 0x01000000);
for (i = 0; i < code->size / 4; i++) {
if ((i & 0x3f) == 0)
nvkm_wr32(device, fuc_base + 0x0188, i >> 6);
nvkm_wr32(device, fuc_base + 0x0184, code->data[i]);
}
/* code must be padded to 0x40 words */
for (; i & 0x3f; i++)
nvkm_wr32(device, fuc_base + 0x0184, 0);
nvkm_falcon_load_dmem(falcon, data->data, 0x0, data->size, 0);
nvkm_falcon_load_imem(falcon, code->data, 0x0, code->size, 0, 0, false);
}
static void
@ -1471,14 +1456,14 @@ gf100_gr_init_ctxctl_ext(struct gf100_gr *gr)
if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_FECS))
ret = nvkm_secboot_reset(sb, NVKM_SECBOOT_FALCON_FECS);
else
gf100_gr_init_fw(gr, 0x409000, &gr->fuc409c, &gr->fuc409d);
gf100_gr_init_fw(gr->fecs, &gr->fuc409c, &gr->fuc409d);
if (ret)
return ret;
if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_GPCCS))
ret = nvkm_secboot_reset(sb, NVKM_SECBOOT_FALCON_GPCCS);
else
gf100_gr_init_fw(gr, 0x41a000, &gr->fuc41ac, &gr->fuc41ad);
gf100_gr_init_fw(gr->gpccs, &gr->fuc41ac, &gr->fuc41ad);
if (ret)
return ret;
@ -1489,14 +1474,9 @@ gf100_gr_init_ctxctl_ext(struct gf100_gr *gr)
nvkm_wr32(device, 0x41a10c, 0x00000000);
nvkm_wr32(device, 0x40910c, 0x00000000);
if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_GPCCS))
nvkm_secboot_start(sb, NVKM_SECBOOT_FALCON_GPCCS);
else
nvkm_wr32(device, 0x41a100, 0x00000002);
if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_FECS))
nvkm_secboot_start(sb, NVKM_SECBOOT_FALCON_FECS);
else
nvkm_wr32(device, 0x409100, 0x00000002);
nvkm_falcon_start(gr->gpccs);
nvkm_falcon_start(gr->fecs);
if (nvkm_msec(device, 2000,
if (nvkm_rd32(device, 0x409800) & 0x00000001)
break;
@ -1586,7 +1566,6 @@ gf100_gr_init_ctxctl_int(struct gf100_gr *gr)
const struct gf100_grctx_func *grctx = gr->func->grctx;
struct nvkm_subdev *subdev = &gr->base.engine.subdev;
struct nvkm_device *device = subdev->device;
int i;
if (!gr->func->fecs.ucode) {
return -ENOSYS;
@ -1594,28 +1573,16 @@ gf100_gr_init_ctxctl_int(struct gf100_gr *gr)
/* load HUB microcode */
nvkm_mc_unk260(device, 0);
nvkm_wr32(device, 0x4091c0, 0x01000000);
for (i = 0; i < gr->func->fecs.ucode->data.size / 4; i++)
nvkm_wr32(device, 0x4091c4, gr->func->fecs.ucode->data.data[i]);
nvkm_wr32(device, 0x409180, 0x01000000);
for (i = 0; i < gr->func->fecs.ucode->code.size / 4; i++) {
if ((i & 0x3f) == 0)
nvkm_wr32(device, 0x409188, i >> 6);
nvkm_wr32(device, 0x409184, gr->func->fecs.ucode->code.data[i]);
}
nvkm_falcon_load_dmem(gr->fecs, gr->func->fecs.ucode->data.data, 0x0,
gr->func->fecs.ucode->data.size, 0);
nvkm_falcon_load_imem(gr->fecs, gr->func->fecs.ucode->code.data, 0x0,
gr->func->fecs.ucode->code.size, 0, 0, false);
/* load GPC microcode */
nvkm_wr32(device, 0x41a1c0, 0x01000000);
for (i = 0; i < gr->func->gpccs.ucode->data.size / 4; i++)
nvkm_wr32(device, 0x41a1c4, gr->func->gpccs.ucode->data.data[i]);
nvkm_wr32(device, 0x41a180, 0x01000000);
for (i = 0; i < gr->func->gpccs.ucode->code.size / 4; i++) {
if ((i & 0x3f) == 0)
nvkm_wr32(device, 0x41a188, i >> 6);
nvkm_wr32(device, 0x41a184, gr->func->gpccs.ucode->code.data[i]);
}
nvkm_falcon_load_dmem(gr->gpccs, gr->func->gpccs.ucode->data.data, 0x0,
gr->func->gpccs.ucode->data.size, 0);
nvkm_falcon_load_imem(gr->gpccs, gr->func->gpccs.ucode->code.data, 0x0,
gr->func->gpccs.ucode->code.size, 0, 0, false);
nvkm_mc_unk260(device, 1);
/* load register lists */
@ -1729,10 +1696,32 @@ static int
gf100_gr_init_(struct nvkm_gr *base)
{
struct gf100_gr *gr = gf100_gr(base);
struct nvkm_subdev *subdev = &base->engine.subdev;
u32 ret;
nvkm_pmu_pgob(gr->base.engine.subdev.device->pmu, false);
ret = nvkm_falcon_get(gr->fecs, subdev);
if (ret)
return ret;
ret = nvkm_falcon_get(gr->gpccs, subdev);
if (ret)
return ret;
return gr->func->init(gr);
}
static int
gf100_gr_fini_(struct nvkm_gr *base, bool suspend)
{
struct gf100_gr *gr = gf100_gr(base);
struct nvkm_subdev *subdev = &gr->base.engine.subdev;
nvkm_falcon_put(gr->gpccs, subdev);
nvkm_falcon_put(gr->fecs, subdev);
return 0;
}
void
gf100_gr_dtor_fw(struct gf100_gr_fuc *fuc)
{
@ -1755,6 +1744,9 @@ gf100_gr_dtor(struct nvkm_gr *base)
gr->func->dtor(gr);
kfree(gr->data);
nvkm_falcon_del(&gr->gpccs);
nvkm_falcon_del(&gr->fecs);
gf100_gr_dtor_fw(&gr->fuc409c);
gf100_gr_dtor_fw(&gr->fuc409d);
gf100_gr_dtor_fw(&gr->fuc41ac);
@ -1773,6 +1765,7 @@ gf100_gr_ = {
.dtor = gf100_gr_dtor,
.oneinit = gf100_gr_oneinit,
.init = gf100_gr_init_,
.fini = gf100_gr_fini_,
.intr = gf100_gr_intr,
.units = gf100_gr_units,
.chan_new = gf100_gr_chan_new,
@ -1846,6 +1839,7 @@ int
gf100_gr_ctor(const struct gf100_gr_func *func, struct nvkm_device *device,
int index, struct gf100_gr *gr)
{
struct nvkm_subdev *subdev = &gr->base.engine.subdev;
int ret;
gr->func = func;
@ -1858,7 +1852,11 @@ gf100_gr_ctor(const struct gf100_gr_func *func, struct nvkm_device *device,
if (ret)
return ret;
return 0;
ret = nvkm_falcon_v1_new(subdev, "FECS", 0x409000, &gr->fecs);
if (ret)
return ret;
return nvkm_falcon_v1_new(subdev, "GPCCS", 0x41a000, &gr->gpccs);
}
int

View File

@ -29,6 +29,7 @@
#include <core/gpuobj.h>
#include <subdev/ltc.h>
#include <subdev/mmu.h>
#include <engine/falcon.h>
#define GPC_MAX 32
#define TPC_MAX_PER_GPC 8
@ -75,6 +76,8 @@ struct gf100_gr {
const struct gf100_gr_func *func;
struct nvkm_gr base;
struct nvkm_falcon *fecs;
struct nvkm_falcon *gpccs;
struct gf100_gr_fuc fuc409c;
struct gf100_gr_fuc fuc409d;
struct gf100_gr_fuc fuc41ac;