Skip to content

Commit

Permalink
drm/nouveau/gr/gf100-: select implementation based on available FW
Browse files Browse the repository at this point in the history
This will allow for further customisation of the subdev depending on what
firmware is available.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
  • Loading branch information
Ben Skeggs committed Jan 15, 2020
1 parent a096ff1 commit ef16dc2
Show file tree
Hide file tree
Showing 27 changed files with 498 additions and 329 deletions.
156 changes: 67 additions & 89 deletions drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
Original file line number Diff line number Diff line change
Expand Up @@ -2055,86 +2055,8 @@ gf100_gr_ = {
};

int
gf100_gr_ctor_fw_legacy(struct gf100_gr *gr, const char *fwname,
struct nvkm_blob *fuc, int ret)
{
struct nvkm_subdev *subdev = &gr->base.engine.subdev;
struct nvkm_device *device = subdev->device;
const struct firmware *fw;
char f[32];

/* see if this firmware has a legacy path */
if (!strcmp(fwname, "fecs_inst"))
fwname = "fuc409c";
else if (!strcmp(fwname, "fecs_data"))
fwname = "fuc409d";
else if (!strcmp(fwname, "gpccs_inst"))
fwname = "fuc41ac";
else if (!strcmp(fwname, "gpccs_data"))
fwname = "fuc41ad";
else {
/* nope, let's just return the error we got */
nvkm_error(subdev, "failed to load %s\n", fwname);
return ret;
}

/* yes, try to load from the legacy path */
nvkm_debug(subdev, "%s: falling back to legacy path\n", fwname);

snprintf(f, sizeof(f), "nouveau/nv%02x_%s", device->chipset, fwname);
ret = request_firmware(&fw, f, device->dev);
if (ret) {
snprintf(f, sizeof(f), "nouveau/%s", fwname);
ret = request_firmware(&fw, f, device->dev);
if (ret) {
nvkm_error(subdev, "failed to load %s\n", fwname);
return ret;
}
}

fuc->size = fw->size;
fuc->data = kmemdup(fw->data, fuc->size, GFP_KERNEL);
release_firmware(fw);
return (fuc->data != NULL) ? 0 : -ENOMEM;
}

int
gf100_gr_ctor_fw(struct gf100_gr *gr, const char *fwname,
struct nvkm_blob *fuc)
{
const struct firmware *fw;
int ret;

ret = nvkm_firmware_get(&gr->base.engine.subdev, fwname, &fw);
if (ret) {
ret = gf100_gr_ctor_fw_legacy(gr, fwname, fuc, ret);
if (ret)
return -ENODEV;
return 0;
}

fuc->size = fw->size;
fuc->data = kmemdup(fw->data, fuc->size, GFP_KERNEL);
nvkm_firmware_put(fw);
return (fuc->data != NULL) ? 0 : -ENOMEM;
}

int
gf100_gr_ctor(const struct gf100_gr_func *func, struct nvkm_device *device,
int index, struct gf100_gr *gr)
{
gr->func = func;
gr->firmware = nvkm_boolopt(device->cfgopt, "NvGrUseFW",
func->fecs.ucode == NULL);

return nvkm_gr_ctor(&gf100_gr_, device, index,
gr->firmware || func->fecs.ucode != NULL,
&gr->base);
}

int
gf100_gr_new_(const struct gf100_gr_func *func, struct nvkm_device *device,
int index, struct nvkm_gr **pgr)
gf100_gr_new_(const struct gf100_gr_fwif *fwif,
struct nvkm_device *device, int index, struct nvkm_gr **pgr)
{
struct gf100_gr *gr;
int ret;
Expand All @@ -2143,18 +2065,15 @@ gf100_gr_new_(const struct gf100_gr_func *func, struct nvkm_device *device,
return -ENOMEM;
*pgr = &gr->base;

ret = gf100_gr_ctor(func, device, index, gr);
ret = nvkm_gr_ctor(&gf100_gr_, device, index, true, &gr->base);
if (ret)
return ret;

if (gr->firmware) {
if (gf100_gr_ctor_fw(gr, "fecs_inst", &gr->fecs.inst) ||
gf100_gr_ctor_fw(gr, "fecs_data", &gr->fecs.data) ||
gf100_gr_ctor_fw(gr, "gpccs_inst", &gr->gpccs.inst) ||
gf100_gr_ctor_fw(gr, "gpccs_data", &gr->gpccs.data))
return -ENODEV;
}
fwif = nvkm_firmware_load(&gr->base.engine.subdev, fwif, "Gr", gr);
if (IS_ERR(fwif))
return -ENODEV;

gr->func = fwif->func;
return 0;
}

Expand Down Expand Up @@ -2457,8 +2376,67 @@ gf100_gr = {
}
};

int
gf100_gr_nofw(struct gf100_gr *gr, int ver, const struct gf100_gr_fwif *fwif)
{
gr->firmware = false;
return 0;
}

static int
gf100_gr_load_fw(struct gf100_gr *gr, const char *name,
struct nvkm_blob *blob)
{
struct nvkm_subdev *subdev = &gr->base.engine.subdev;
struct nvkm_device *device = subdev->device;
const struct firmware *fw;
char f[32];
int ret;

snprintf(f, sizeof(f), "nouveau/nv%02x_%s", device->chipset, name);
ret = request_firmware(&fw, f, device->dev);
if (ret) {
snprintf(f, sizeof(f), "nouveau/%s", name);
ret = request_firmware(&fw, f, device->dev);
if (ret) {
nvkm_error(subdev, "failed to load %s\n", name);
return ret;
}
}

blob->size = fw->size;
blob->data = kmemdup(fw->data, blob->size, GFP_KERNEL);
release_firmware(fw);
return (blob->data != NULL) ? 0 : -ENOMEM;
}

int
gf100_gr_load(struct gf100_gr *gr, int ver, const struct gf100_gr_fwif *fwif)
{
struct nvkm_device *device = gr->base.engine.subdev.device;

if (!nvkm_boolopt(device->cfgopt, "NvGrUseFW", false))
return -EINVAL;

if (gf100_gr_load_fw(gr, "fuc409c", &gr->fecs.inst) ||
gf100_gr_load_fw(gr, "fuc409d", &gr->fecs.data) ||
gf100_gr_load_fw(gr, "fuc41ac", &gr->gpccs.inst) ||
gf100_gr_load_fw(gr, "fuc41ad", &gr->gpccs.data))
return -ENOENT;

gr->firmware = true;
return 0;
}

static const struct gf100_gr_fwif
gf100_gr_fwif[] = {
{ -1, gf100_gr_load, &gf100_gr },
{ -1, gf100_gr_nofw, &gf100_gr },
{}
};

int
gf100_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr)
{
return gf100_gr_new_(&gf100_gr, device, index, pgr);
return gf100_gr_new_(gf100_gr_fwif, device, index, pgr);
}
38 changes: 25 additions & 13 deletions drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,12 +136,6 @@ struct gf100_gr {
u32 size_pm;
};

int gf100_gr_ctor(const struct gf100_gr_func *, struct nvkm_device *,
int, struct gf100_gr *);
int gf100_gr_new_(const struct gf100_gr_func *, struct nvkm_device *,
int, struct nvkm_gr **);
void *gf100_gr_dtor(struct nvkm_gr *);

int gf100_gr_fecs_bind_pointer(struct gf100_gr *, u32 inst);

struct gf100_gr_func_zbc {
Expand Down Expand Up @@ -247,8 +241,6 @@ extern const struct gf100_gr_func_zbc gp102_gr_zbc;

extern const struct gf100_gr_func gp107_gr;

int gk20a_gr_load_sw(struct gf100_gr *, const char *path, int ver);

#define gf100_gr_chan(p) container_of((p), struct gf100_gr_chan, object)
#include <core/object.h>

Expand All @@ -269,8 +261,6 @@ struct gf100_gr_chan {

void gf100_gr_ctxctl_debug(struct gf100_gr *);

int gf100_gr_ctor_fw(struct gf100_gr *, const char *,
struct nvkm_blob *);
u64 gf100_gr_units(struct nvkm_gr *);
void gf100_gr_zbc_init(struct gf100_gr *);

Expand Down Expand Up @@ -309,9 +299,6 @@ void gf100_gr_icmd(struct gf100_gr *, const struct gf100_gr_pack *);
void gf100_gr_mthd(struct gf100_gr *, const struct gf100_gr_pack *);
int gf100_gr_init_ctxctl(struct gf100_gr *);

int gm200_gr_new_(const struct gf100_gr_func *, struct nvkm_device *, int,
struct nvkm_gr **);

/* register init value lists */

extern const struct gf100_gr_init gf100_gr_init_main_0[];
Expand Down Expand Up @@ -394,4 +381,29 @@ extern const struct gf100_gr_init gm107_gr_init_cbm_0[];
void gm107_gr_init_bios(struct gf100_gr *);

void gm200_gr_init_gpc_mmu(struct gf100_gr *);

struct gf100_gr_fwif {
int version;
int (*load)(struct gf100_gr *, int ver, const struct gf100_gr_fwif *);
const struct gf100_gr_func *func;
const struct nvkm_acr_lsf_func *fecs;
const struct nvkm_acr_lsf_func *gpccs;
};

int gf100_gr_load(struct gf100_gr *, int, const struct gf100_gr_fwif *);
int gf100_gr_nofw(struct gf100_gr *, int, const struct gf100_gr_fwif *);

int gk20a_gr_load_sw(struct gf100_gr *, const char *path, int ver);

int gm200_gr_load(struct gf100_gr *, int, const struct gf100_gr_fwif *);
extern const struct nvkm_acr_lsf_func gm200_gr_gpccs_acr;
extern const struct nvkm_acr_lsf_func gm200_gr_fecs_acr;

extern const struct nvkm_acr_lsf_func gm20b_gr_fecs_acr;

extern const struct nvkm_acr_lsf_func gp108_gr_gpccs_acr;
extern const struct nvkm_acr_lsf_func gp108_gr_fecs_acr;

int gf100_gr_new_(const struct gf100_gr_fwif *, struct nvkm_device *, int,
struct nvkm_gr **);
#endif
9 changes: 8 additions & 1 deletion drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,15 @@ gf104_gr = {
}
};

static const struct gf100_gr_fwif
gf104_gr_fwif[] = {
{ -1, gf100_gr_load, &gf104_gr },
{ -1, gf100_gr_nofw, &gf104_gr },
{}
};

int
gf104_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr)
{
return gf100_gr_new_(&gf104_gr, device, index, pgr);
return gf100_gr_new_(gf104_gr_fwif, device, index, pgr);
}
9 changes: 8 additions & 1 deletion drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,15 @@ gf108_gr = {
}
};

const struct gf100_gr_fwif
gf108_gr_fwif[] = {
{ -1, gf100_gr_load, &gf108_gr },
{ -1, gf100_gr_nofw, &gf108_gr },
{}
};

int
gf108_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr)
{
return gf100_gr_new_(&gf108_gr, device, index, pgr);
return gf100_gr_new_(gf108_gr_fwif, device, index, pgr);
}
9 changes: 8 additions & 1 deletion drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,15 @@ gf110_gr = {
}
};

static const struct gf100_gr_fwif
gf110_gr_fwif[] = {
{ -1, gf100_gr_load, &gf110_gr },
{ -1, gf100_gr_nofw, &gf110_gr },
{}
};

int
gf110_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr)
{
return gf100_gr_new_(&gf110_gr, device, index, pgr);
return gf100_gr_new_(gf110_gr_fwif, device, index, pgr);
}
9 changes: 8 additions & 1 deletion drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,15 @@ gf117_gr = {
}
};

static const struct gf100_gr_fwif
gf117_gr_fwif[] = {
{ -1, gf100_gr_load, &gf117_gr },
{ -1, gf100_gr_nofw, &gf117_gr },
{}
};

int
gf117_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr)
{
return gf100_gr_new_(&gf117_gr, device, index, pgr);
return gf100_gr_new_(gf117_gr_fwif, device, index, pgr);
}
9 changes: 8 additions & 1 deletion drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c
Original file line number Diff line number Diff line change
Expand Up @@ -210,8 +210,15 @@ gf119_gr = {
}
};

static const struct gf100_gr_fwif
gf119_gr_fwif[] = {
{ -1, gf100_gr_load, &gf119_gr },
{ -1, gf100_gr_nofw, &gf119_gr },
{}
};

int
gf119_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr)
{
return gf100_gr_new_(&gf119_gr, device, index, pgr);
return gf100_gr_new_(gf119_gr_fwif, device, index, pgr);
}
9 changes: 8 additions & 1 deletion drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c
Original file line number Diff line number Diff line change
Expand Up @@ -489,8 +489,15 @@ gk104_gr = {
}
};

static const struct gf100_gr_fwif
gk104_gr_fwif[] = {
{ -1, gf100_gr_load, &gk104_gr },
{ -1, gf100_gr_nofw, &gk104_gr },
{}
};

int
gk104_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr)
{
return gf100_gr_new_(&gk104_gr, device, index, pgr);
return gf100_gr_new_(gk104_gr_fwif, device, index, pgr);
}
9 changes: 8 additions & 1 deletion drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c
Original file line number Diff line number Diff line change
Expand Up @@ -385,8 +385,15 @@ gk110_gr = {
}
};

static const struct gf100_gr_fwif
gk110_gr_fwif[] = {
{ -1, gf100_gr_load, &gk110_gr },
{ -1, gf100_gr_nofw, &gk110_gr },
{}
};

int
gk110_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr)
{
return gf100_gr_new_(&gk110_gr, device, index, pgr);
return gf100_gr_new_(gk110_gr_fwif, device, index, pgr);
}
9 changes: 8 additions & 1 deletion drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,15 @@ gk110b_gr = {
}
};

static const struct gf100_gr_fwif
gk110b_gr_fwif[] = {
{ -1, gf100_gr_load, &gk110b_gr },
{ -1, gf100_gr_nofw, &gk110b_gr },
{}
};

int
gk110b_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr)
{
return gf100_gr_new_(&gk110b_gr, device, index, pgr);
return gf100_gr_new_(gk110b_gr_fwif, device, index, pgr);
}
Loading

0 comments on commit ef16dc2

Please sign in to comment.