diff --git a/drivers/gpu/nvgpu/Makefile b/drivers/gpu/nvgpu/Makefile index 49d7f6884..cf00d222d 100644 --- a/drivers/gpu/nvgpu/Makefile +++ b/drivers/gpu/nvgpu/Makefile @@ -77,6 +77,7 @@ nvgpu-y += \ common/gr/ctxsw_prog/ctxsw_prog_gv11b.o \ common/gr/global_ctx.o \ common/gr/ctx.o \ + common/gr/gr_falcon.o \ common/gr/subctx.o \ common/gr/zcull.o \ common/gr/config/gr_config.o \ diff --git a/drivers/gpu/nvgpu/Makefile.sources b/drivers/gpu/nvgpu/Makefile.sources index 8345311b6..22ef51505 100644 --- a/drivers/gpu/nvgpu/Makefile.sources +++ b/drivers/gpu/nvgpu/Makefile.sources @@ -113,6 +113,7 @@ srcs += common/sim.c \ common/gr/global_ctx.c \ common/gr/subctx.c \ common/gr/ctx.c \ + common/gr/gr_falcon.c \ common/gr/zcull.c \ common/gr/config/gr_config.c \ common/gr/fecs_trace/fecs_trace.c \ diff --git a/drivers/gpu/nvgpu/common/acr/acr_blob_construct_v0.c b/drivers/gpu/nvgpu/common/acr/acr_blob_construct_v0.c index bac460216..1089bcf5d 100644 --- a/drivers/gpu/nvgpu/common/acr/acr_blob_construct_v0.c +++ b/drivers/gpu/nvgpu/common/acr/acr_blob_construct_v0.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "acr_blob_construct_v0.h" #include "acr_priv.h" @@ -796,7 +797,7 @@ int nvgpu_acr_prepare_ucode_blob_v0(struct gk20a *g) (void) memset((void *)plsfm, 0, sizeof(struct ls_flcn_mgr)); nvgpu_acr_dbg(g, "fetching GMMU regs\n"); g->ops.fb.vpr_info_fetch(g); - gr_gk20a_init_ctxsw_ucode(g); + nvgpu_gr_falcon_init_ctxsw_ucode(g); g->acr->get_wpr_info(g, &wpr_inf); nvgpu_acr_dbg(g, "wpr carveout base:%llx\n", wpr_inf.wpr_base); diff --git a/drivers/gpu/nvgpu/common/acr/acr_blob_construct_v1.c b/drivers/gpu/nvgpu/common/acr/acr_blob_construct_v1.c index 4e6183fc5..10a76b02a 100644 --- a/drivers/gpu/nvgpu/common/acr/acr_blob_construct_v1.c +++ b/drivers/gpu/nvgpu/common/acr/acr_blob_construct_v1.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "acr_blob_construct_v1.h" #include "acr_priv.h" @@ -935,7 +936,7 @@ int nvgpu_acr_prepare_ucode_blob_v1(struct gk20a *g) plsfm = &lsfm_l; (void) memset((void *)plsfm, 0, sizeof(struct ls_flcn_mgr_v1)); - gr_gk20a_init_ctxsw_ucode(g); + nvgpu_gr_falcon_init_ctxsw_ucode(g); g->acr->get_wpr_info(g, &wpr_inf); nvgpu_acr_dbg(g, "wpr carveout base:%llx\n", (wpr_inf.wpr_base)); diff --git a/drivers/gpu/nvgpu/common/gr/gr_falcon.c b/drivers/gpu/nvgpu/common/gr/gr_falcon.c new file mode 100644 index 000000000..08cb155e4 --- /dev/null +++ b/drivers/gpu/nvgpu/common/gr/gr_falcon.c @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2019, 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. + */ + +#include +#include +#include +#include +#include + +static int nvgpu_gr_falcon_init_ctxsw_ucode_vaspace(struct gk20a *g) +{ + struct mm_gk20a *mm = &g->mm; + struct vm_gk20a *vm = mm->pmu.vm; + struct gk20a_ctxsw_ucode_info *ucode_info = &g->ctxsw_ucode_info; + int err; + + err = g->ops.mm.alloc_inst_block(g, &ucode_info->inst_blk_desc); + if (err != 0) { + return err; + } + + g->ops.mm.init_inst_block(&ucode_info->inst_blk_desc, vm, 0); + + /* Map ucode surface to GMMU */ + ucode_info->surface_desc.gpu_va = nvgpu_gmmu_map(vm, + &ucode_info->surface_desc, + ucode_info->surface_desc.size, + 0, /* flags */ + gk20a_mem_flag_read_only, + false, + ucode_info->surface_desc.aperture); + if (ucode_info->surface_desc.gpu_va == 0ULL) { + nvgpu_err(g, "failed to update gmmu ptes"); + return -ENOMEM; + } + + return 0; +} + +static void nvgpu_gr_falcon_init_ctxsw_ucode_segment( + struct gk20a_ctxsw_ucode_segment *p_seg, u32 *offset, u32 size) +{ + p_seg->offset = *offset; + p_seg->size = size; + *offset = ALIGN(*offset + size, SZ_256); +} + +static void nvgpu_gr_falcon_init_ctxsw_ucode_segments( + struct gk20a_ctxsw_ucode_segments *segments, u32 *offset, + struct gk20a_ctxsw_bootloader_desc *bootdesc, + u32 code_size, u32 data_size) +{ + u32 boot_size = ALIGN(bootdesc->size, sizeof(u32)); + + segments->boot_entry = bootdesc->entry_point; + segments->boot_imem_offset = bootdesc->imem_offset; + nvgpu_gr_falcon_init_ctxsw_ucode_segment(&segments->boot, + offset, boot_size); + nvgpu_gr_falcon_init_ctxsw_ucode_segment(&segments->code, + offset, code_size); + nvgpu_gr_falcon_init_ctxsw_ucode_segment(&segments->data, + offset, data_size); +} + +static int nvgpu_gr_falcon_copy_ctxsw_ucode_segments( + struct gk20a *g, + struct nvgpu_mem *dst, + struct gk20a_ctxsw_ucode_segments *segments, + u32 *bootimage, + u32 *code, u32 *data) +{ + unsigned int i; + + nvgpu_mem_wr_n(g, dst, segments->boot.offset, bootimage, + segments->boot.size); + nvgpu_mem_wr_n(g, dst, segments->code.offset, code, + segments->code.size); + nvgpu_mem_wr_n(g, dst, segments->data.offset, data, + segments->data.size); + + /* compute a "checksum" for the boot binary to detect its version */ + segments->boot_signature = 0; + for (i = 0; i < segments->boot.size / sizeof(u32); i++) { + segments->boot_signature += bootimage[i]; + } + + return 0; +} + +int nvgpu_gr_falcon_init_ctxsw_ucode(struct gk20a *g) +{ + struct mm_gk20a *mm = &g->mm; + struct vm_gk20a *vm = mm->pmu.vm; + struct gk20a_ctxsw_bootloader_desc *fecs_boot_desc; + struct gk20a_ctxsw_bootloader_desc *gpccs_boot_desc; + struct nvgpu_firmware *fecs_fw; + struct nvgpu_firmware *gpccs_fw; + u32 *fecs_boot_image; + u32 *gpccs_boot_image; + struct gk20a_ctxsw_ucode_info *ucode_info = &g->ctxsw_ucode_info; + u32 ucode_size; + int err = 0; + + fecs_fw = nvgpu_request_firmware(g, GK20A_FECS_UCODE_IMAGE, 0); + if (fecs_fw == NULL) { + nvgpu_err(g, "failed to load fecs ucode!!"); + return -ENOENT; + } + + fecs_boot_desc = (void *)fecs_fw->data; + fecs_boot_image = (void *)(fecs_fw->data + + sizeof(struct gk20a_ctxsw_bootloader_desc)); + + gpccs_fw = nvgpu_request_firmware(g, GK20A_GPCCS_UCODE_IMAGE, 0); + if (gpccs_fw == NULL) { + nvgpu_release_firmware(g, fecs_fw); + nvgpu_err(g, "failed to load gpccs ucode!!"); + return -ENOENT; + } + + gpccs_boot_desc = (void *)gpccs_fw->data; + gpccs_boot_image = (void *)(gpccs_fw->data + + sizeof(struct gk20a_ctxsw_bootloader_desc)); + + ucode_size = 0; + nvgpu_gr_falcon_init_ctxsw_ucode_segments(&ucode_info->fecs, + &ucode_size, fecs_boot_desc, + g->netlist_vars->ucode.fecs.inst.count * (u32)sizeof(u32), + g->netlist_vars->ucode.fecs.data.count * (u32)sizeof(u32)); + nvgpu_gr_falcon_init_ctxsw_ucode_segments(&ucode_info->gpccs, + &ucode_size, gpccs_boot_desc, + g->netlist_vars->ucode.gpccs.inst.count * (u32)sizeof(u32), + g->netlist_vars->ucode.gpccs.data.count * (u32)sizeof(u32)); + + err = nvgpu_dma_alloc_sys(g, ucode_size, &ucode_info->surface_desc); + if (err != 0) { + goto clean_up; + } + + nvgpu_gr_falcon_copy_ctxsw_ucode_segments(g, &ucode_info->surface_desc, + &ucode_info->fecs, + fecs_boot_image, + g->netlist_vars->ucode.fecs.inst.l, + g->netlist_vars->ucode.fecs.data.l); + + nvgpu_release_firmware(g, fecs_fw); + fecs_fw = NULL; + + nvgpu_gr_falcon_copy_ctxsw_ucode_segments(g, &ucode_info->surface_desc, + &ucode_info->gpccs, + gpccs_boot_image, + g->netlist_vars->ucode.gpccs.inst.l, + g->netlist_vars->ucode.gpccs.data.l); + + nvgpu_release_firmware(g, gpccs_fw); + gpccs_fw = NULL; + + err = nvgpu_gr_falcon_init_ctxsw_ucode_vaspace(g); + if (err != 0) { + goto clean_up; + } + + return 0; + +clean_up: + if (ucode_info->surface_desc.gpu_va != 0ULL) { + nvgpu_gmmu_unmap(vm, &ucode_info->surface_desc, + ucode_info->surface_desc.gpu_va); + } + nvgpu_dma_free(g, &ucode_info->surface_desc); + + nvgpu_release_firmware(g, gpccs_fw); + gpccs_fw = NULL; + nvgpu_release_firmware(g, fecs_fw); + fecs_fw = NULL; + + return err; +} diff --git a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c index ad1da85c1..fe4dfcf31 100644 --- a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -1109,172 +1110,6 @@ static void gr_gk20a_start_falcon_ucode(struct gk20a *g) nvgpu_log_fn(g, "done"); } -static int gr_gk20a_init_ctxsw_ucode_vaspace(struct gk20a *g) -{ - struct mm_gk20a *mm = &g->mm; - struct vm_gk20a *vm = mm->pmu.vm; - struct gk20a_ctxsw_ucode_info *ucode_info = &g->ctxsw_ucode_info; - int err; - - err = g->ops.mm.alloc_inst_block(g, &ucode_info->inst_blk_desc); - if (err != 0) { - return err; - } - - g->ops.mm.init_inst_block(&ucode_info->inst_blk_desc, vm, 0); - - /* Map ucode surface to GMMU */ - ucode_info->surface_desc.gpu_va = nvgpu_gmmu_map(vm, - &ucode_info->surface_desc, - ucode_info->surface_desc.size, - 0, /* flags */ - gk20a_mem_flag_read_only, - false, - ucode_info->surface_desc.aperture); - if (ucode_info->surface_desc.gpu_va == 0ULL) { - nvgpu_err(g, "failed to update gmmu ptes"); - return -ENOMEM; - } - - return 0; -} - -static void gr_gk20a_init_ctxsw_ucode_segment( - struct gk20a_ctxsw_ucode_segment *p_seg, u32 *offset, u32 size) -{ - p_seg->offset = *offset; - p_seg->size = size; - *offset = ALIGN(*offset + size, BLK_SIZE); -} - -static void gr_gk20a_init_ctxsw_ucode_segments( - struct gk20a_ctxsw_ucode_segments *segments, u32 *offset, - struct gk20a_ctxsw_bootloader_desc *bootdesc, - u32 code_size, u32 data_size) -{ - u32 boot_size = ALIGN(bootdesc->size, sizeof(u32)); - segments->boot_entry = bootdesc->entry_point; - segments->boot_imem_offset = bootdesc->imem_offset; - gr_gk20a_init_ctxsw_ucode_segment(&segments->boot, offset, boot_size); - gr_gk20a_init_ctxsw_ucode_segment(&segments->code, offset, code_size); - gr_gk20a_init_ctxsw_ucode_segment(&segments->data, offset, data_size); -} - -static int gr_gk20a_copy_ctxsw_ucode_segments( - struct gk20a *g, - struct nvgpu_mem *dst, - struct gk20a_ctxsw_ucode_segments *segments, - u32 *bootimage, - u32 *code, u32 *data) -{ - unsigned int i; - - nvgpu_mem_wr_n(g, dst, segments->boot.offset, bootimage, - segments->boot.size); - nvgpu_mem_wr_n(g, dst, segments->code.offset, code, - segments->code.size); - nvgpu_mem_wr_n(g, dst, segments->data.offset, data, - segments->data.size); - - /* compute a "checksum" for the boot binary to detect its version */ - segments->boot_signature = 0; - for (i = 0; i < segments->boot.size / sizeof(u32); i++) { - segments->boot_signature += bootimage[i]; - } - - return 0; -} - -int gr_gk20a_init_ctxsw_ucode(struct gk20a *g) -{ - struct mm_gk20a *mm = &g->mm; - struct vm_gk20a *vm = mm->pmu.vm; - struct gk20a_ctxsw_bootloader_desc *fecs_boot_desc; - struct gk20a_ctxsw_bootloader_desc *gpccs_boot_desc; - struct nvgpu_firmware *fecs_fw; - struct nvgpu_firmware *gpccs_fw; - u32 *fecs_boot_image; - u32 *gpccs_boot_image; - struct gk20a_ctxsw_ucode_info *ucode_info = &g->ctxsw_ucode_info; - u32 ucode_size; - int err = 0; - - fecs_fw = nvgpu_request_firmware(g, GK20A_FECS_UCODE_IMAGE, 0); - if (fecs_fw == NULL) { - nvgpu_err(g, "failed to load fecs ucode!!"); - return -ENOENT; - } - - fecs_boot_desc = (void *)fecs_fw->data; - fecs_boot_image = (void *)(fecs_fw->data + - sizeof(struct gk20a_ctxsw_bootloader_desc)); - - gpccs_fw = nvgpu_request_firmware(g, GK20A_GPCCS_UCODE_IMAGE, 0); - if (gpccs_fw == NULL) { - nvgpu_release_firmware(g, fecs_fw); - nvgpu_err(g, "failed to load gpccs ucode!!"); - return -ENOENT; - } - - gpccs_boot_desc = (void *)gpccs_fw->data; - gpccs_boot_image = (void *)(gpccs_fw->data + - sizeof(struct gk20a_ctxsw_bootloader_desc)); - - ucode_size = 0; - gr_gk20a_init_ctxsw_ucode_segments(&ucode_info->fecs, &ucode_size, - fecs_boot_desc, - g->netlist_vars->ucode.fecs.inst.count * (u32)sizeof(u32), - g->netlist_vars->ucode.fecs.data.count * (u32)sizeof(u32)); - gr_gk20a_init_ctxsw_ucode_segments(&ucode_info->gpccs, &ucode_size, - gpccs_boot_desc, - g->netlist_vars->ucode.gpccs.inst.count * (u32)sizeof(u32), - g->netlist_vars->ucode.gpccs.data.count * (u32)sizeof(u32)); - - err = nvgpu_dma_alloc_sys(g, ucode_size, &ucode_info->surface_desc); - if (err != 0) { - goto clean_up; - } - - gr_gk20a_copy_ctxsw_ucode_segments(g, &ucode_info->surface_desc, - &ucode_info->fecs, - fecs_boot_image, - g->netlist_vars->ucode.fecs.inst.l, - g->netlist_vars->ucode.fecs.data.l); - - nvgpu_release_firmware(g, fecs_fw); - fecs_fw = NULL; - - gr_gk20a_copy_ctxsw_ucode_segments(g, &ucode_info->surface_desc, - &ucode_info->gpccs, - gpccs_boot_image, - g->netlist_vars->ucode.gpccs.inst.l, - g->netlist_vars->ucode.gpccs.data.l); - - nvgpu_release_firmware(g, gpccs_fw); - gpccs_fw = NULL; - - err = gr_gk20a_init_ctxsw_ucode_vaspace(g); - if (err != 0) { - goto clean_up; - } - - return 0; - -clean_up: - if (ucode_info->surface_desc.gpu_va != 0ULL) { - nvgpu_gmmu_unmap(vm, &ucode_info->surface_desc, - ucode_info->surface_desc.gpu_va); - } - nvgpu_dma_free(g, &ucode_info->surface_desc); - - nvgpu_release_firmware(g, gpccs_fw); - gpccs_fw = NULL; - nvgpu_release_firmware(g, fecs_fw); - fecs_fw = NULL; - - return err; -} - static void gr_gk20a_wait_for_fecs_arb_idle(struct gk20a *g) { int retries = FECS_ARB_CMD_TIMEOUT_MAX / FECS_ARB_CMD_TIMEOUT_DEFAULT; @@ -1528,7 +1363,7 @@ int gr_gk20a_load_ctxsw_ucode(struct gk20a *g) gr_gk20a_start_falcon_ucode(g); } else { if (!g->gr.skip_ucode_init) { - err = gr_gk20a_init_ctxsw_ucode(g); + err = nvgpu_gr_falcon_init_ctxsw_ucode(g); if (err != 0) { return err; diff --git a/drivers/gpu/nvgpu/gk20a/gr_gk20a.h b/drivers/gpu/nvgpu/gk20a/gr_gk20a.h index 1f2c16699..cddddbf02 100644 --- a/drivers/gpu/nvgpu/gk20a/gr_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gr_gk20a.h @@ -351,7 +351,6 @@ int gr_gk20a_update_hwpm_ctxsw_mode(struct gk20a *g, void gk20a_gr_set_shader_exceptions(struct gk20a *g, u32 data); void gr_gk20a_enable_hww_exceptions(struct gk20a *g); -int gr_gk20a_init_ctxsw_ucode(struct gk20a *g); int gr_gk20a_load_ctxsw_ucode(struct gk20a *g); void gr_gk20a_load_falcon_bind_instblk(struct gk20a *g); void gr_gk20a_load_ctxsw_ucode_header(struct gk20a *g, u64 addr_base, diff --git a/drivers/gpu/nvgpu/include/nvgpu/gr/gr_falcon.h b/drivers/gpu/nvgpu/include/nvgpu/gr/gr_falcon.h new file mode 100644 index 000000000..5fd5f1db6 --- /dev/null +++ b/drivers/gpu/nvgpu/include/nvgpu/gr/gr_falcon.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2019, 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. + */ + +#ifndef NVGPU_GR_FALCON_H +#define NVGPU_GR_FALCON_H + +#include + +struct gk20a; + +int nvgpu_gr_falcon_init_ctxsw_ucode(struct gk20a *g); + +#endif /* NVGPU_GR_SUBCTX_H */