diff options
Diffstat (limited to 'drm/nouveau/nvkm')
-rw-r--r-- | drm/nouveau/nvkm/engine/gr/gf100.c | 96 | ||||
-rw-r--r-- | drm/nouveau/nvkm/engine/gr/netlist.h | 76 |
2 files changed, 172 insertions, 0 deletions
diff --git a/drm/nouveau/nvkm/engine/gr/gf100.c b/drm/nouveau/nvkm/engine/gr/gf100.c index 1dd482e9d..b751d0dc4 100644 --- a/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drm/nouveau/nvkm/engine/gr/gf100.c @@ -24,6 +24,11 @@ #include "gf100.h" #include "ctxgf100.h" #include "fuc/os.h" +#include "netlist.h" + +#ifdef __KERNEL__ +#include <nouveau_platform.h> +#endif #include <core/client.h> #include <core/device.h> @@ -1519,6 +1524,89 @@ gf100_gr_ctor_fw(struct gf100_gr_priv *priv, const char *fwname, return (fuc->data != NULL) ? 0 : -ENOMEM; } +static int +duplicate_netlist_region(const struct firmware *fw, + struct netlist_region *region, + struct gf100_gr_fuc *fuc) +{ + fuc->size = region->data_size; + fuc->data = kmemdup(fw->data + region->data_offset, fuc->size, + GFP_KERNEL); + if (!fuc->data) + return -ENOMEM; + + return 0; +} + +static int +gf100_graph_ctor_fw_netlist(struct gf100_gr_priv *priv) +{ + struct nvkm_device *device = nv_device(priv); + struct nouveau_platform_device *platdev; + struct netlist_image *netimage; + const struct firmware *fw; + const u32 required_fw = BIT(NETLIST_REGIONID_FECS_UCODE_DATA) | + BIT(NETLIST_REGIONID_FECS_UCODE_INST) | + BIT(NETLIST_REGIONID_GPCCS_UCODE_DATA) | + BIT(NETLIST_REGIONID_GPCCS_UCODE_INST); + u32 loaded_fw = 0; + int i; + + /* Are we a platform device? */ + if (!device->platformdev) + return 0; + + platdev = nv_device_to_platform(device); + fw = platdev->gpu->ctxsw_fw; + /* No firmware loaded? */ + if (!fw) + return 0; + + netimage = (struct netlist_image *)fw->data; + for (i = 0; i < netimage->header.regions; i++) { + struct netlist_region region = netimage->regions[i]; + int err = 0; + + if (loaded_fw & BIT(region.region_id)) { + nv_warn(priv, "skipping already loaded fw region\n"); + continue; + } + + switch (region.region_id) { + case NETLIST_REGIONID_FECS_UCODE_DATA: + err = duplicate_netlist_region(fw, ®ion, + &priv->fuc409d); + break; + case NETLIST_REGIONID_FECS_UCODE_INST: + err = duplicate_netlist_region(fw, ®ion, + &priv->fuc409c); + break; + case NETLIST_REGIONID_GPCCS_UCODE_DATA: + err = duplicate_netlist_region(fw, ®ion, + &priv->fuc41ad); + break; + case NETLIST_REGIONID_GPCCS_UCODE_INST: + err = duplicate_netlist_region(fw, ®ion, + &priv->fuc41ac); + break; + } + + if (err) + return err; + + loaded_fw |= BIT(region.region_id); + } + + /* Check that all FWs have been loaded */ + if ((loaded_fw & required_fw) != required_fw) { + nv_error(priv, "firmwares missing from the netlist image!\n"); + return -EINVAL; + } + + priv->firmware = true; + return 0; +} + void gf100_gr_dtor(struct nvkm_object *object) { @@ -1563,6 +1651,14 @@ gf100_gr_ctor(struct nvkm_object *parent, struct nvkm_object *engine, priv->base.units = gf100_gr_units; if (use_ext_fw) { + /* First look for a netlist blob */ + ret = gf100_graph_ctor_fw_netlist(priv); + if (ret) + return ret; + } + + /* Legacy firmware loading if no netlist was present */ + if (use_ext_fw && !priv->firmware) { nv_info(priv, "using external firmware\n"); if (gf100_gr_ctor_fw(priv, "fuc409c", &priv->fuc409c) || gf100_gr_ctor_fw(priv, "fuc409d", &priv->fuc409d) || diff --git a/drm/nouveau/nvkm/engine/gr/netlist.h b/drm/nouveau/nvkm/engine/gr/netlist.h new file mode 100644 index 000000000..0c1a90986 --- /dev/null +++ b/drm/nouveau/nvkm/engine/gr/netlist.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +/** + * Contains definitions of the structures used to pack NVIDIA + * officially-released firmwares. + */ + +#ifndef __GRAPH_NETLIST_H__ +#define __GRAPH_NETLIST_H__ + +#include <core/os.h> + +/* netlist regions */ +#define NETLIST_REGIONID_FECS_UCODE_DATA 0 +#define NETLIST_REGIONID_FECS_UCODE_INST 1 +#define NETLIST_REGIONID_GPCCS_UCODE_DATA 2 +#define NETLIST_REGIONID_GPCCS_UCODE_INST 3 +#define NETLIST_REGIONID_SW_BUNDLE_INIT 4 +#define NETLIST_REGIONID_SW_CTX_LOAD 5 +#define NETLIST_REGIONID_SW_NON_CTX_LOAD 6 +#define NETLIST_REGIONID_SW_METHOD_INIT 7 +#define NETLIST_REGIONID_CTXREG_SYS 8 +#define NETLIST_REGIONID_CTXREG_GPC 9 +#define NETLIST_REGIONID_CTXREG_TPC 10 +#define NETLIST_REGIONID_CTXREG_ZCULL_GPC 11 +#define NETLIST_REGIONID_CTXREG_PM_SYS 12 +#define NETLIST_REGIONID_CTXREG_PM_GPC 13 +#define NETLIST_REGIONID_CTXREG_PM_TPC 14 +#define NETLIST_REGIONID_MAJORV 15 +#define NETLIST_REGIONID_BUFFER_SIZE 16 +#define NETLIST_REGIONID_CTXSW_REG_BASE_INDEX 17 +#define NETLIST_REGIONID_NETLIST_NUM 18 +#define NETLIST_REGIONID_CTXREG_PPC 19 +#define NETLIST_REGIONID_CTXREG_PMPPC 20 + +struct netlist_region +{ + u32 region_id; + u32 data_size; + u32 data_offset; +}; + +struct netlist_image_header +{ + u32 version; + u32 regions; +}; + +struct netlist_image +{ + struct netlist_image_header header; + struct netlist_region regions[1]; +}; + +#endif |