diff --git a/arch/nvgpu-common.yaml b/arch/nvgpu-common.yaml index 78f4d5f52..e9e24d221 100644 --- a/arch/nvgpu-common.yaml +++ b/arch/nvgpu-common.yaml @@ -418,7 +418,8 @@ falcon: common/falcon/falcon_debug.c, common/falcon/falcon_debug.h, include/nvgpu/gops/gsp.h, - include/nvgpu/gops/nvdec.h ] + include/nvgpu/gops/nvdec.h, + include/nvgpu/gops/nvenc.h ] deps: [ ] tags: @@ -1173,6 +1174,25 @@ gin: sources: [ include/nvgpu/gops/gin.h, include/nvgpu/gin.h ] +multimedia: + safe: no + owner: santosh B S + children: + multimedia_common: + safe: no + gpu: both + sources: [ common/multimedia/multimedia.c, + common/multimedia/multimedia_priv.h, + include/nvgpu/multimedia.h ] + + nvenc: + safe: no + owner: santosh B S + gpu: both + sources: [ common/multimedia/nvenc.c, + common/multimedia/nvenc_bootstrap.h, + include/nvgpu/nvenc.h ] + ## ## HAL units. Currently they are under common but this needs to change. ## We are moving these to a top level directory. diff --git a/arch/nvgpu-gpu_hw.yaml b/arch/nvgpu-gpu_hw.yaml index 232721763..c6176f8f7 100644 --- a/arch/nvgpu-gpu_hw.yaml +++ b/arch/nvgpu-gpu_hw.yaml @@ -1,4 +1,4 @@ -# Copyright (c) 2019-2021, NVIDIA CORPORATION. All Rights Reserved. +# Copyright (c) 2019-2023, NVIDIA CORPORATION. All Rights Reserved. # # Define meta elements and units for describing GPU HW interactions in # nvgpu. @@ -206,6 +206,7 @@ headers: include/nvgpu/hw/tu104/hw_perf_tu104.h, include/nvgpu/hw/tu104/hw_pgsp_tu104.h, include/nvgpu/hw/tu104/hw_pnvdec_tu104.h, + include/nvgpu/hw/tu104/hw_pnvenc_tu104.h, include/nvgpu/hw/tu104/hw_pram_tu104.h, include/nvgpu/hw/tu104/hw_pri_ringmaster_tu104.h, include/nvgpu/hw/tu104/hw_pri_ringstation_gpc_tu104.h, diff --git a/arch/nvgpu-hal-new.yaml b/arch/nvgpu-hal-new.yaml index b4ab29661..86a4684a5 100644 --- a/arch/nvgpu-hal-new.yaml +++ b/arch/nvgpu-hal-new.yaml @@ -1,4 +1,4 @@ -# Copyright (c) 2019-2022, NVIDIA CORPORATION. All Rights Reserved. +# Copyright (c) 2019-2023, NVIDIA CORPORATION. All Rights Reserved. # # HAL units. These are the units that have access to HW. # @@ -914,14 +914,23 @@ netlist: hal/netlist/netlist_ga100.c, hal/netlist/netlist_ga100.h ] -nvdec: +multimedia: safe: no - sources: [ hal/nvdec/nvdec_gp106.c, - hal/nvdec/nvdec_gp106.h, - hal/nvdec/nvdec_tu104.c, - hal/nvdec/nvdec_tu104.h, - hal/nvdec/nvdec_ga100.c, - hal/nvdec/nvdec_ga100.h ] + owner: santosh B S + children: + nvdec: + safe: no + sources: [ hal/nvdec/nvdec_gp106.c, + hal/nvdec/nvdec_gp106.h, + hal/nvdec/nvdec_tu104.c, + hal/nvdec/nvdec_tu104.h, + hal/nvdec/nvdec_ga100.c, + hal/nvdec/nvdec_ga100.h ] + + nvenc: + safe: no + sources: [ hal/nvenc/nvenc_tu104.c, + hal/nvenc/nvenc_tu104.h ] perf: safe: no diff --git a/drivers/gpu/nvgpu/Makefile b/drivers/gpu/nvgpu/Makefile index 7a2647d4e..3ee93e8e5 100644 --- a/drivers/gpu/nvgpu/Makefile +++ b/drivers/gpu/nvgpu/Makefile @@ -201,6 +201,7 @@ nvgpu-$(CONFIG_NVGPU_DGPU) += \ hal/netlist/netlist_tu104.o \ hal/nvdec/nvdec_gp106.o \ hal/nvdec/nvdec_tu104.o \ + hal/nvenc/nvenc_tu104.o \ hal/gsp/gsp_tu104.o \ hal/sec2/sec2_tu104.o \ hal/pramin/pramin_gp10b.o \ @@ -359,6 +360,8 @@ nvgpu-y += \ common/cic/mon/mon_report_err.o \ common/cic/rm/rm_init.o \ common/cic/rm/rm_intr.o \ + common/multimedia/nvenc.o \ + common/multimedia/multimedia.o \ hal/bus/bus_gk20a.o \ hal/class/class_gm20b.o \ hal/class/class_gp10b.o \ diff --git a/drivers/gpu/nvgpu/Makefile.sources b/drivers/gpu/nvgpu/Makefile.sources index c3f976c93..02f86f740 100644 --- a/drivers/gpu/nvgpu/Makefile.sources +++ b/drivers/gpu/nvgpu/Makefile.sources @@ -171,6 +171,8 @@ srcs += common/device.c \ common/cic/mon/mon_report_err.c \ common/cic/rm/rm_init.c \ common/cic/rm/rm_intr.c \ + common/multimedia/nvenc.c \ + common/multimedia/multimedia.c \ hal/init/hal_gv11b_litter.c \ hal/init/hal_init.c \ hal/power_features/cg/gv11b_gating_reglist.c \ @@ -751,6 +753,7 @@ srcs += common/sec2/sec2.c \ hal/netlist/netlist_tu104.c \ hal/nvdec/nvdec_gp106.c \ hal/nvdec/nvdec_tu104.c \ + hal/nvenc/nvenc_tu104.c \ hal/gsp/gsp_tu104.c \ hal/sec2/sec2_tu104.c \ hal/pramin/pramin_gp10b.c \ diff --git a/drivers/gpu/nvgpu/common/falcon/falcon.c b/drivers/gpu/nvgpu/common/falcon/falcon.c index b4a7fdc2d..2d358bb80 100644 --- a/drivers/gpu/nvgpu/common/falcon/falcon.c +++ b/drivers/gpu/nvgpu/common/falcon/falcon.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2022, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2017-2023, 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"), @@ -476,6 +476,9 @@ struct nvgpu_falcon *nvgpu_falcon_get_instance(struct gk20a *g, u32 flcn_id) case FALCON_ID_NVDEC: flcn = &g->nvdec_flcn; break; + case FALCON_ID_NVENC: + flcn = &g->nvenc_flcn; + break; case FALCON_ID_SEC2: flcn = &g->sec2.flcn; break; @@ -862,3 +865,27 @@ void nvgpu_falcon_get_ctls(struct nvgpu_falcon *flcn, u32 *sctl, u32 *cpuctl) flcn->g->ops.falcon.get_falcon_ctls(flcn, sctl, cpuctl); } #endif + +s32 nvgpu_falcon_load_ucode(struct nvgpu_falcon *flcn, + struct nvgpu_mem *ucode_mem_desc, u32 *ucode_header) +{ + s32 status = -EINVAL; + struct gk20a *g; + + if (!is_falcon_valid(flcn)) { + return -EINVAL; + } + + g = flcn->g; + + if (g->ops.falcon.load_ucode == NULL) { + nvgpu_err(g, "hal for loading ucode not set"); + goto exit; + } + + /* Load ucode */ + status = g->ops.falcon.load_ucode(flcn, ucode_mem_desc, ucode_header); + +exit: + return status; +} diff --git a/drivers/gpu/nvgpu/common/falcon/falcon_sw_tu104.c b/drivers/gpu/nvgpu/common/falcon/falcon_sw_tu104.c index fc92380d6..acb85f458 100644 --- a/drivers/gpu/nvgpu/common/falcon/falcon_sw_tu104.c +++ b/drivers/gpu/nvgpu/common/falcon/falcon_sw_tu104.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2018-2023, 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"), @@ -47,6 +47,10 @@ void tu104_falcon_engine_dependency_ops(struct nvgpu_falcon *flcn) flcn_eng_dep_ops->copy_from_emem = g->ops.sec2.sec2_copy_from_emem; break; + case FALCON_ID_NVENC: + flcn_eng_dep_ops->setup_bootstrap_config = + g->ops.nvenc.setup_boot_config; + break; default: flcn_eng_dep_ops->reset_eng = NULL; break; @@ -79,6 +83,11 @@ void tu104_falcon_sw_init(struct nvgpu_falcon *flcn) flcn->is_falcon_supported = true; flcn->is_interrupt_enabled = true; break; + case FALCON_ID_NVENC: + flcn->flcn_base = g->ops.nvenc.base_addr(); + flcn->is_falcon_supported = true; + flcn->is_interrupt_enabled = true; + break; default: /* * set false to inherit falcon support diff --git a/drivers/gpu/nvgpu/common/fifo/engines.c b/drivers/gpu/nvgpu/common/fifo/engines.c index b545d8e33..f965cafc5 100644 --- a/drivers/gpu/nvgpu/common/fifo/engines.c +++ b/drivers/gpu/nvgpu/common/fifo/engines.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2022, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2019-2023, 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"), @@ -62,6 +62,8 @@ enum nvgpu_fifo_engine nvgpu_engine_enum_from_dev(struct gk20a *g, * comparsion logic with GR runlist_id in init_info() */ ret = NVGPU_ENGINE_ASYNC_CE; + } else if (nvgpu_device_is_nvenc(g, dev)) { + ret = NVGPU_ENGINE_NVENC; } else { ret = NVGPU_ENGINE_INVAL; } @@ -520,15 +522,16 @@ void nvgpu_engine_reset(struct gk20a *g, u32 engine_id) } if (!nvgpu_device_is_ce(g, dev) && - !nvgpu_device_is_graphics(g, dev)) { + !nvgpu_device_is_graphics(g, dev) && + !nvgpu_device_is_nvenc(g, dev)) { nvgpu_warn(g, "Ignoring reset for non-host engine."); return; } - /* - * Simple case first: reset a copy engine. - */ if (nvgpu_device_is_ce(g, dev)) { + /* + * Simple case first: reset a copy engine. + */ if (g->ops.ce.halt_engine != NULL) { g->ops.ce.halt_engine(g, dev); } @@ -544,18 +547,24 @@ void nvgpu_engine_reset(struct gk20a *g, u32 engine_id) nvgpu_log_info(g, "CE engine [id:%u] reset failed", dev->engine_id); } - return; + } else if (nvgpu_device_is_nvenc(g, dev)) { + /* Reset nvenc engine. */ + err = g->ops.nvenc.reset(g); + if (err != 0) { + nvgpu_log(g, gpu_dbg_info, "NVENC engine [id:%u] reset failed", + dev->engine_id); + } + } else { + /* + * Now reset a GR engine. + */ + gr_instance_id = + nvgpu_grmgr_get_gr_instance_id_for_syspipe( + g, dev->inst_id); + + nvgpu_gr_exec_for_instance(g, + gr_instance_id, nvgpu_engine_gr_reset(g)); } - - /* - * Now reset a GR engine. - */ - gr_instance_id = - nvgpu_grmgr_get_gr_instance_id_for_syspipe( - g, dev->inst_id); - - nvgpu_gr_exec_for_instance(g, - gr_instance_id, nvgpu_engine_gr_reset(g)); } #endif @@ -616,6 +625,18 @@ u32 nvgpu_engine_get_gr_runlist_id(struct gk20a *g) return dev->runlist_id; } +u32 nvgpu_engine_get_nvenc_runlist_id(struct gk20a *g) +{ + const struct nvgpu_device *dev; + + dev = nvgpu_device_get(g, NVGPU_DEVTYPE_NVENC, 0); + if (dev == NULL) { + return NVGPU_INVALID_RUNLIST_ID; + } + + return dev->runlist_id; +} + bool nvgpu_engine_is_valid_runlist_id(struct gk20a *g, u32 runlist_id) { u32 i; @@ -632,6 +653,20 @@ bool nvgpu_engine_is_valid_runlist_id(struct gk20a *g, u32 runlist_id) return false; } +bool nvgpu_engine_is_multimedia_runlist_id(struct gk20a *g, u32 runlist_id) +{ + const struct nvgpu_device *dev; + + /* Will be extended for other multimedia engine types */ + nvgpu_device_for_each(g, dev, NVGPU_DEVTYPE_NVENC) { + if (dev->runlist_id == runlist_id) { + return true; + } + } + + return false; +} + /* * Link engine IDs to MMU IDs and vice versa. */ @@ -865,7 +900,14 @@ int nvgpu_engine_init_info(struct nvgpu_fifo *f) } } - return g->ops.engine.init_ce_info(f); + nvgpu_device_for_each(g, dev, NVGPU_DEVTYPE_NVENC) { + err = nvgpu_engine_init_one_dev(f, dev); + if (err != 0) { + return err; + } + } + err = g->ops.engine.init_ce_info(f); + return err; } void nvgpu_engine_get_id_and_type(struct gk20a *g, u32 engine_id, diff --git a/drivers/gpu/nvgpu/common/fifo/tsg.c b/drivers/gpu/nvgpu/common/fifo/tsg.c index 87412305d..34f8ccfdc 100644 --- a/drivers/gpu/nvgpu/common/fifo/tsg.c +++ b/drivers/gpu/nvgpu/common/fifo/tsg.c @@ -42,6 +42,7 @@ #ifdef CONFIG_NVGPU_PROFILER #include #endif +#include #define MATCH_VEID true #define MATCH_PBDMA_ID true @@ -478,11 +479,14 @@ int nvgpu_tsg_bind_channel(struct nvgpu_tsg *tsg, struct nvgpu_channel *ch) } nvgpu_rwsem_down_write(&tsg->ch_list_lock); - err = nvgpu_tsg_subctx_bind_channel(tsg, ch); - if (err != 0) { - nvgpu_err(g, "Subcontext %u bind failed", ch->subctx_id); - nvgpu_rwsem_up_write(&tsg->ch_list_lock); - return err; + /* As multimedia engines are non-VEID engines, subctx is not needed */ + if (!nvgpu_engine_is_multimedia_runlist_id(g, ch->runlist->id)) { + err = nvgpu_tsg_subctx_bind_channel(tsg, ch); + if (err != 0) { + nvgpu_err(g, "Subcontext %u bind failed", ch->subctx_id); + nvgpu_rwsem_up_write(&tsg->ch_list_lock); + return err; + } } nvgpu_list_add_tail(&ch->ch_entry, &tsg->ch_list); @@ -630,7 +634,9 @@ static int nvgpu_tsg_unbind_channel_common(struct nvgpu_tsg *tsg, g->ops.channel.unbind(ch); nvgpu_rwsem_down_write(&tsg->ch_list_lock); - nvgpu_tsg_subctx_unbind_channel(tsg, ch); + if (!nvgpu_engine_is_multimedia_runlist_id(g, ch->runlist->id)) { + nvgpu_tsg_subctx_unbind_channel(tsg, ch); + } nvgpu_list_del(&ch->ch_entry); tsg->ch_count = nvgpu_safe_sub_u32(tsg->ch_count, 1U); ch->tsgid = NVGPU_INVALID_TSG_ID; @@ -844,6 +850,7 @@ static void nvgpu_tsg_destroy(struct nvgpu_tsg *tsg) nvgpu_mutex_destroy(&tsg->tsg_share_lock); #endif nvgpu_mutex_destroy(&tsg->ctx_init_lock); + nvgpu_mutex_destroy(&tsg->eng_ctx_lock); nvgpu_mutex_destroy(&tsg->veid_alloc_lock); } @@ -899,6 +906,7 @@ static void nvgpu_tsg_init_support(struct gk20a *g, u32 tsgid) nvgpu_init_list_node(&tsg->gr_ctx_mappings_list); nvgpu_rwsem_init(&tsg->ch_list_lock); nvgpu_mutex_init(&tsg->ctx_init_lock); + nvgpu_mutex_init(&tsg->eng_ctx_lock); nvgpu_mutex_init(&tsg->veid_alloc_lock); #ifdef CONFIG_NVGPU_CHANNEL_TSG_CONTROL @@ -1466,6 +1474,8 @@ void nvgpu_tsg_release(struct nvgpu_ref *ref) g->ops.gr.setup.free_gr_ctx(g, gr_ctx); } + nvgpu_multimedia_free_all_ctx(tsg); + #ifdef CONFIG_NVGPU_CHANNEL_TSG_CONTROL /* unhook all events created on this TSG */ nvgpu_mutex_acquire(&tsg->event_id_list_lock); diff --git a/drivers/gpu/nvgpu/common/init/nvgpu_init.c b/drivers/gpu/nvgpu/common/init/nvgpu_init.c index c6ea2f4c3..bbfd197c9 100644 --- a/drivers/gpu/nvgpu/common/init/nvgpu_init.c +++ b/drivers/gpu/nvgpu/common/init/nvgpu_init.c @@ -266,17 +266,25 @@ static int nvgpu_falcons_sw_init(struct gk20a *g) goto done_sec2; } + err = g->ops.falcon.falcon_sw_init(g, FALCON_ID_NVENC); + if (err != 0) { + nvgpu_err(g, "failed to sw init FALCON_ID_NVENC"); + goto done_nvdec; + } + #endif err = g->ops.falcon.falcon_sw_init(g, FALCON_ID_GSPLITE); if (err != 0) { nvgpu_err(g, "failed to sw init FALCON_ID_GSPLITE"); - goto done_nvdec; + goto done_nvenc; } return 0; -done_nvdec: +done_nvenc: #ifdef CONFIG_NVGPU_DGPU + g->ops.falcon.falcon_sw_free(g, FALCON_ID_NVENC); +done_nvdec: g->ops.falcon.falcon_sw_free(g, FALCON_ID_NVDEC); done_sec2: g->ops.falcon.falcon_sw_free(g, FALCON_ID_SEC2); @@ -302,6 +310,7 @@ static void nvgpu_falcons_sw_free(struct gk20a *g) #ifdef CONFIG_NVGPU_DGPU g->ops.falcon.falcon_sw_free(g, FALCON_ID_GSPLITE); g->ops.falcon.falcon_sw_free(g, FALCON_ID_NVDEC); + g->ops.falcon.falcon_sw_free(g, FALCON_ID_NVENC); g->ops.falcon.falcon_sw_free(g, FALCON_ID_SEC2); #endif } @@ -342,6 +351,13 @@ int nvgpu_prepare_poweroff(struct gk20a *g) ret = tmp_ret; } } + + if (nvgpu_is_enabled(g, NVGPU_SUPPORT_MULTIMEDIA)) { + tmp_ret = g->ops.nvenc.deinit(g); + if (tmp_ret != 0) { + ret = tmp_ret; + } + } #endif tmp_ret = g->ops.gr.gr_suspend(g); if (tmp_ret != 0) { @@ -969,6 +985,8 @@ int nvgpu_finalize_poweron(struct gk20a *g) NVGPU_INIT_TABLE_ENTRY(&nvgpu_init_cg_ctrl_load_gating_prod, NO_FLAG), #ifdef CONFIG_NVGPU_DGPU + NVGPU_INIT_TABLE_ENTRY(g->ops.nvenc.init, NVGPU_SUPPORT_MULTIMEDIA), + NVGPU_INIT_TABLE_ENTRY(g->ops.nvenc.bootstrap, NVGPU_SUPPORT_MULTIMEDIA), NVGPU_INIT_TABLE_ENTRY(g->ops.sec2.init_sec2_support, NVGPU_SUPPORT_SEC2_RTOS), #endif diff --git a/drivers/gpu/nvgpu/common/multimedia/multimedia.c b/drivers/gpu/nvgpu/common/multimedia/multimedia.c new file mode 100644 index 000000000..659c88fc8 --- /dev/null +++ b/drivers/gpu/nvgpu/common/multimedia/multimedia.c @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2023, 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "multimedia_priv.h" +#include "nvenc_bootstrap.h" + +/* Engine ctx buffer size. 256-byte aligned */ +#define MULTIMEDIA_CTX_BUF_SIZE (4096U) + +static u32 nvgpu_multimedia_get_id(struct gk20a *g, u32 class) +{ + u32 multimedia_id = NVGPU_MULTIMEDIA_ENGINE_MAX; + + if (g->ops.gpu_class.is_valid_nvenc != NULL) { + if (g->ops.gpu_class.is_valid_nvenc(class)) { + multimedia_id = NVGPU_MULTIMEDIA_ENGINE_NVENC; + } + } + + return multimedia_id; +} + +int nvgpu_multimedia_setup_ctx(struct nvgpu_channel *ch, u32 class_num, u32 flags) +{ + struct gk20a *g = ch->g; + struct nvgpu_tsg *tsg = NULL; + struct nvgpu_mem *ctx_mem; + u32 multimedia_id; + int err = 0; + (void) flags; + + /* An address space has already been bound by this point.*/ + if (!nvgpu_channel_as_bound(ch)) { + nvgpu_err(g, "not bound to an address space by the time of" + " eng ctx allocation"); + return -EINVAL; + } + + if ((g->ops.gpu_class.is_valid_multimedia == NULL) || + !g->ops.gpu_class.is_valid_multimedia(class_num)) { + return -EINVAL; + } + + ch->obj_class = class_num; + tsg = nvgpu_tsg_from_ch(ch); + if (tsg == NULL) { + return -EINVAL; + } + + nvgpu_mutex_acquire(&tsg->eng_ctx_lock); + + g->ops.tsg.disable(tsg); + + err = nvgpu_tsg_preempt(g, tsg); + if (err != 0) { + nvgpu_err(g, "tsg preempt failed %d", err); + goto enable_tsg; + } + + err = nvgpu_tsg_validate_class_veid_pbdma(ch); + if (err != 0) { + nvgpu_err(g, "Invalid class/veid/pbdma config"); + goto enable_tsg; + } + + multimedia_id = nvgpu_multimedia_get_id(g, ch->obj_class); + if (multimedia_id >= NVGPU_MULTIMEDIA_ENGINE_MAX) { + nvgpu_err(g, "Invalid multimedia id %d", multimedia_id); + err = -EINVAL; + goto enable_tsg; + } + + if (tsg->eng_ctx[multimedia_id] == NULL) { + /* + * Engine ctx buffer has already been allocated for this engine + * in this TSG. + */ + goto enable_tsg; + } + + tsg->eng_ctx[multimedia_id] = nvgpu_kzalloc(g, sizeof(struct nvgpu_multimedia_ctx)); + + tsg->eng_ctx[multimedia_id]->tsgid = tsg->tsgid; + + ctx_mem = &tsg->eng_ctx[multimedia_id]->ctx_mem; + err = nvgpu_dma_alloc_sys(g, MULTIMEDIA_CTX_BUF_SIZE, ctx_mem); + if (err != 0) { + nvgpu_err(g, "failed to allocate a ctx buffer for engine %d", multimedia_id); + goto free_eng_ctx; + } + + ctx_mem->gpu_va = nvgpu_gmmu_map(ch->vm, ctx_mem, + 0, /* not GPU-cacheable */ + gk20a_mem_flag_none, false, + ctx_mem->aperture); + if (ctx_mem->gpu_va == 0ULL) { + nvgpu_err(g, "failed to map ctx buffer"); + err = -ENOMEM; + goto free_ctx_mem; + } + + /* Clear the context memory */ + nvgpu_memset(g, ctx_mem, 0U, 0U, MULTIMEDIA_CTX_BUF_SIZE); + + /* Set the context pointer in the inst block */ + g->ops.ramin.set_gr_ptr(g, &ch->inst_block, ctx_mem->gpu_va); + + /* Engine ctx setup is fine. Return 0 */ + goto enable_tsg; + +free_ctx_mem: + nvgpu_dma_free(g, ctx_mem); + +free_eng_ctx: + nvgpu_kfree(g, tsg->eng_ctx[multimedia_id]); + tsg->eng_ctx[multimedia_id] = NULL; + +enable_tsg: + g->ops.tsg.enable(tsg); + nvgpu_mutex_release(&tsg->eng_ctx_lock); + + return err; +} + +void nvgpu_multimedia_free_ctx(struct gk20a *g, struct nvgpu_multimedia_ctx *eng_ctx) +{ + struct nvgpu_tsg *tsg; + struct nvgpu_mem *ctx_mem; + + if (eng_ctx != NULL) { + ctx_mem = &eng_ctx->ctx_mem; + tsg = nvgpu_tsg_get_from_id(g, eng_ctx->tsgid); + + nvgpu_mutex_acquire(&tsg->eng_ctx_lock); + if (nvgpu_mem_is_valid(ctx_mem)) { + nvgpu_dma_free(g, ctx_mem); + } + nvgpu_kfree(g, eng_ctx); + nvgpu_mutex_release(&tsg->eng_ctx_lock); + } +} + +void nvgpu_multimedia_free_all_ctx(struct nvgpu_tsg *tsg) +{ + enum nvgpu_multimedia_engine eng; + struct nvgpu_multimedia_ctx *eng_ctx; + struct gk20a *g = tsg->g; + + nvgpu_mutex_acquire(&tsg->eng_ctx_lock); + + for (eng = NVGPU_MULTIMEDIA_ENGINE_NVENC; eng < NVGPU_MULTIMEDIA_ENGINE_MAX; eng++) { + eng_ctx = tsg->eng_ctx[eng]; + if (eng_ctx != NULL) { + if (nvgpu_mem_is_valid(&eng_ctx->ctx_mem)) { + nvgpu_dma_free(g, &eng_ctx->ctx_mem); + } + nvgpu_kfree(g, eng_ctx); + tsg->eng_ctx[eng] = NULL; + } + } + + nvgpu_mutex_release(&tsg->eng_ctx_lock); +} + +int nvgpu_multimedia_copy_fw(struct gk20a *g, const char *fw_name, u32 *ucode_header, + struct nvgpu_mem *ucode_mem_desc) +{ + struct nvgpu_firmware *multimedia_fw; + struct multimedia_fw_hdr *fw_hdr = NULL; + void *ucode = NULL; + int err = 0; + + nvgpu_log(g, gpu_dbg_info, "Loading the firmware: %s", fw_name); + + multimedia_fw = nvgpu_request_firmware(g, fw_name, + NVGPU_REQUEST_FIRMWARE_NO_WARN); + if (multimedia_fw == NULL) { + nvgpu_err(g, "Failed to read firmware: %s", fw_name); + return -ENOENT; + } + + fw_hdr = (struct multimedia_fw_hdr *) multimedia_fw->data; + nvgpu_memcpy((u8 *)ucode_header, multimedia_fw->data + fw_hdr->header_offset, + MULTIMEDIA_UCODE_HEADER_SIZE_BYTES); + ucode = multimedia_fw->data + fw_hdr->data_offset; + + nvgpu_log(g, gpu_dbg_info, "firmware header: magic= 0x%x ver= 0x%x size= 0x%x", + fw_hdr->fw_magic, + fw_hdr->fw_ver, + fw_hdr->fw_size); + nvgpu_log(g, gpu_dbg_info, "firmware header: ucode header offset= 0x%x, " + "data (offset,size): 0x%x 0x%x", + fw_hdr->header_offset, + fw_hdr->data_offset, + fw_hdr->data_size); + nvgpu_log(g, gpu_dbg_info, "ucode header: code (offset,size): 0x%x, 0x%x", + ucode_header[OS_CODE_OFFSET], + ucode_header[OS_CODE_SIZE]); + nvgpu_log(g, gpu_dbg_info, "ucode header: data (offset,size): 0x%x, 0x%x", + ucode_header[OS_DATA_OFFSET], + ucode_header[OS_DATA_SIZE]); + + /* Alloc mem space for holding the ucode, that will be DMA'ed to the engine */ + if (!nvgpu_mem_is_valid(ucode_mem_desc)) { + err = nvgpu_dma_alloc_flags_sys(g, + NVGPU_DMA_PHYSICALLY_ADDRESSED, + fw_hdr->data_size, + ucode_mem_desc); + if (err != 0) { + nvgpu_err(g, "sys mem alloc for ucode failed"); + goto free_ucode; + } + } + + /* Clear the memory and then copy the ucode */ + nvgpu_memset(g, ucode_mem_desc, 0U, 0U, fw_hdr->data_size); + nvgpu_mem_wr_n(g, ucode_mem_desc, 0U, ucode, fw_hdr->data_size); + +free_ucode: + nvgpu_release_firmware(g, multimedia_fw); + return err; +} diff --git a/drivers/gpu/nvgpu/common/multimedia/multimedia_priv.h b/drivers/gpu/nvgpu/common/multimedia/multimedia_priv.h new file mode 100644 index 000000000..e39d560f1 --- /dev/null +++ b/drivers/gpu/nvgpu/common/multimedia/multimedia_priv.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. 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 MULTIMEDIA_PRIV_H +#define MULTIMEDIA_PRIV_H + +#define TU104_NVENC_UCODE_FW "nvhost_nvenc072.fw" + +#define MULTIMEDIA_UCODE_HEADER_SIZE (APP_0_CODE_SIZE + 1) +#define MULTIMEDIA_UCODE_HEADER_SIZE_BYTES (MULTIMEDIA_UCODE_HEADER_SIZE * 4) + +struct multimedia_fw_hdr { + /* 0x10de */ + u32 fw_magic; + /* Versioning of firmware format */ + u32 fw_ver; + /* Entire image size including this header */ + u32 fw_size; + /* Header offset of executable firmware metadata */ + u32 header_offset; + /* Start of executable firmware data */ + u32 data_offset; + /* Size of executable firmware */ + u32 data_size; + /* Reserved */ + u32 reserved[4]; +}; + +int nvgpu_multimedia_copy_fw(struct gk20a *g, const char *fw_name, u32 *ucode_header, + struct nvgpu_mem *ucode_mem_desc); +#endif /* MULTIMEDIA_PRIV_H */ diff --git a/drivers/gpu/nvgpu/common/multimedia/nvenc.c b/drivers/gpu/nvgpu/common/multimedia/nvenc.c new file mode 100644 index 000000000..e47c1d29d --- /dev/null +++ b/drivers/gpu/nvgpu/common/multimedia/nvenc.c @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include "multimedia_priv.h" +#include "nvenc_bootstrap.h" + +/* NVENC init */ +int nvgpu_nvenc_sw_init(struct gk20a *g) +{ + u32 ver = nvgpu_safe_add_u32(g->params.gpu_arch, + g->params.gpu_impl); + int err = 0; + + if (g->nvenc != NULL) { + /* Initialized already, so reuse the same to perform boot faster */ + return err; + } + + g->nvenc = (struct nvgpu_nvenc *)nvgpu_kzalloc(g, sizeof(struct nvgpu_nvenc)); + if (g->nvenc == NULL) { + err = -ENOMEM; + goto done; + } + + switch (ver) { +#ifdef CONFIG_NVGPU_DGPU + case NVGPU_GPUID_TU104: + g->nvenc->fw_name = TU104_NVENC_UCODE_FW; + g->nvenc->nvenc_flcn = &g->nvenc_flcn; + err = nvgpu_multimedia_copy_fw(g, g->nvenc->fw_name, + g->nvenc->ucode_header, + &g->nvenc->nvenc_mem_desc); + break; +#endif + default: + nvgpu_kfree(g, g->nvenc); + err = -ENODEV; + nvgpu_err(g, "no support for GPUID %x", ver); + break; + } + +done: + return err; +} + +/* NVENC deinit */ +int nvgpu_nvenc_sw_deinit(struct gk20a *g) +{ + struct nvgpu_nvenc *nvenc = g->nvenc; + + nvgpu_dma_free(g, &nvenc->nvenc_mem_desc); + nvgpu_kfree(g, nvenc); + return 0; +} + +/* NVENC falcon boot */ +int nvgpu_nvenc_falcon_boot(struct gk20a *g) +{ + int err = 0; + int completion = 0; + + struct nvgpu_nvenc *nvenc = g->nvenc; + struct nvgpu_falcon *flcn = nvenc->nvenc_flcn; + struct nvgpu_mem *nvenc_mem_desc = &nvenc->nvenc_mem_desc; + u32 *ucode_header = nvenc->ucode_header; + + nvgpu_log_fn(g, " "); + + /* Reset nvenc HW unit */ + err = nvgpu_mc_reset_units(g, NVGPU_UNIT_NVENC); + if (err != 0) { + nvgpu_err(g, "Failed to reset NVENC unit"); + goto done; + } + + /* Falcon reset */ + err = nvgpu_falcon_reset(flcn); + if (err != 0) { + nvgpu_err(g, "nvenc falcon_reset failed, err=%d", err); + goto done; + } + + /* Set falcon interrupt mask and routing registers */ + if (g->ops.nvenc.set_irq_regs != NULL) + g->ops.nvenc.set_irq_regs(g, flcn); + + /* Setup falcon apertures, boot-config */ + if (flcn->flcn_engine_dep_ops.setup_bootstrap_config != NULL) { + flcn->flcn_engine_dep_ops.setup_bootstrap_config(flcn->g); + } + + /* Load nvenc ucode */ + err = nvgpu_falcon_load_ucode(flcn, nvenc_mem_desc, ucode_header); + if (err != 0) { + nvgpu_err(g, "nvenc ucode loading failed, err=%d", err); + goto done; + } + + /* Enable falcon interfaces */ + if (g->ops.nvenc.interface_enable != NULL) + g->ops.nvenc.interface_enable(g); + + /* Kick-start falcon cpu */ + g->ops.falcon.bootstrap(flcn, 0U); + + /* Wait for falcon idle */ + completion = nvgpu_falcon_wait_idle(flcn); + if (completion != 0) { + nvgpu_err(g, "nvenc flcn: ucode boot timed out"); + err = -ETIMEDOUT; + } + + nvgpu_log(g, gpu_dbg_info, "NVENC NS boot %s!", err ? "SUCCESS" : "FAILED"); + +done: + return err; +} + +int nvgpu_nvenc_reset(struct gk20a *g) +{ + int err = 0; + + if (g->ops.nvenc.halt_engine != NULL) { + g->ops.nvenc.halt_engine(g); + } + + /* Reset nvenc HW unit and load ucode */ + err = g->ops.nvenc.bootstrap(g); + + return err; +} diff --git a/drivers/gpu/nvgpu/common/multimedia/nvenc_bootstrap.h b/drivers/gpu/nvgpu/common/multimedia/nvenc_bootstrap.h new file mode 100644 index 000000000..77d942788 --- /dev/null +++ b/drivers/gpu/nvgpu/common/multimedia/nvenc_bootstrap.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2023, 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 NVENC_BOOTSTRAP_H +#define NVENC_BOOTSTRAP_H + +/* NVENC core descriptor */ +struct nvgpu_nvenc { + + /* NVENC ucode */ + const char *fw_name; + + /* NVENC ucode header info */ + u32 ucode_header[MULTIMEDIA_UCODE_HEADER_SIZE]; + + /* Falcon used to execute NVENC ucode */ + struct nvgpu_falcon *nvenc_flcn; + + /** Memory to store ucode contents locally. */ + struct nvgpu_mem nvenc_mem_desc; + +}; + +#endif /* NVENC_BOOTSTRAP_H */ diff --git a/drivers/gpu/nvgpu/hal/class/class_tu104.c b/drivers/gpu/nvgpu/hal/class/class_tu104.c index 81d71a1f4..51fb26fb4 100644 --- a/drivers/gpu/nvgpu/hal/class/class_tu104.c +++ b/drivers/gpu/nvgpu/hal/class/class_tu104.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2019-2023 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"), @@ -36,6 +36,7 @@ bool tu104_class_is_valid(u32 class_num) case TURING_CHANNEL_GPFIFO_A: case TURING_COMPUTE_A: case TURING_DMA_COPY_A: + case TURING_NVENC_A: #ifdef CONFIG_NVGPU_GRAPHICS case TURING_A: #endif @@ -83,3 +84,19 @@ bool tu104_class_is_valid_compute(u32 class_num) } return valid; } + +bool tu104_class_is_valid_nvenc(u32 class_num) +{ + nvgpu_speculation_barrier(); + + if (class_num == TURING_NVENC_A) { + return true; + } else { + return false; + } +} + +bool tu104_class_is_valid_multimedia(u32 class_num) +{ + return tu104_class_is_valid_nvenc(class_num); +} diff --git a/drivers/gpu/nvgpu/hal/class/class_tu104.h b/drivers/gpu/nvgpu/hal/class/class_tu104.h index 520c527bf..3f6a3f127 100644 --- a/drivers/gpu/nvgpu/hal/class/class_tu104.h +++ b/drivers/gpu/nvgpu/hal/class/class_tu104.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2019-2023, 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"), @@ -27,6 +27,8 @@ bool tu104_class_is_valid(u32 class_num); bool tu104_class_is_valid_compute(u32 class_num); +bool tu104_class_is_valid_multimedia(u32 class_num); +bool tu104_class_is_valid_nvenc(u32 class_num); #ifdef CONFIG_NVGPU_GRAPHICS bool tu104_class_is_valid_gfx(u32 class_num); diff --git a/drivers/gpu/nvgpu/hal/falcon/falcon_gk20a.h b/drivers/gpu/nvgpu/hal/falcon/falcon_gk20a.h index e430d91f0..5006102f7 100644 --- a/drivers/gpu/nvgpu/hal/falcon/falcon_gk20a.h +++ b/drivers/gpu/nvgpu/hal/falcon/falcon_gk20a.h @@ -83,6 +83,8 @@ void gk20a_falcon_mailbox_write(struct nvgpu_falcon *flcn, u32 mailbox_index, u32 data); void gk20a_falcon_set_irq(struct nvgpu_falcon *flcn, bool enable, u32 intr_mask, u32 intr_dest); +s32 gk20a_falcon_load_ucode_dma(struct nvgpu_falcon *flcn, + struct nvgpu_mem *mem_desc, u32 *ucode_header); #ifdef CONFIG_NVGPU_FALCON_DEBUG void gk20a_falcon_dump_stats(struct nvgpu_falcon *flcn); diff --git a/drivers/gpu/nvgpu/hal/falcon/falcon_gk20a_fusa.c b/drivers/gpu/nvgpu/hal/falcon/falcon_gk20a_fusa.c index 3093f165f..d49542834 100644 --- a/drivers/gpu/nvgpu/hal/falcon/falcon_gk20a_fusa.c +++ b/drivers/gpu/nvgpu/hal/falcon/falcon_gk20a_fusa.c @@ -29,6 +29,11 @@ #include +#define NVGPU_DMA_CHUNK_SIZE (256U) + +/* Timeout duration in number of retries */ +#define NVGPU_DMA_WAIT_TIMEOUT (2000U) + u32 gk20a_falcon_dmemc_blk_mask(void) { return falcon_falcon_dmemc_blk_m(); @@ -627,3 +632,105 @@ void gk20a_falcon_dump_info(struct nvgpu_falcon *flcn) (falcon_falcon_exterraddr_r() & 0x0FFF))); } #endif + +/* Wait for the dma to be idle before initiating next block */ +static s32 gk20a_falcon_dma_wait_idle(struct nvgpu_falcon *flcn) +{ + struct nvgpu_timeout timeout; + struct gk20a *g; + + if ((flcn == NULL) || (!flcn->is_falcon_supported)) { + return -EINVAL; + } + + g = flcn->g; + + nvgpu_timeout_init_retry(g, &timeout, NVGPU_DMA_WAIT_TIMEOUT); + + /* Wait for falcon idle */ + do { + u32 val = 0U; + + val = nvgpu_falcon_readl(flcn, falcon_falcon_dmatrfcmd_r()); + if (falcon_falcon_dmatrfcmd_idle_v(val) == 0x1U) { + break; + } + + if (nvgpu_timeout_expired_msg(&timeout, + "waiting for dma_wait_idle") != 0) { + return -ETIMEDOUT; + } + + nvgpu_usleep_range(100, 200); + } while (true); + + return 0; +} + +/* DMA transfer the ucode (in terms of 256-byte chunk) to IMEM/DMEM */ +static s32 gk20a_falcon_dma_ucode(struct nvgpu_falcon *flcn, u32 *ucode_header, + bool imem) +{ + u32 i, offset, size; + struct gk20a *g = flcn->g; + u32 flcn_base = flcn->flcn_base; + s32 err = 0; + + offset = imem ? ucode_header[OS_CODE_OFFSET] : ucode_header[OS_DATA_OFFSET]; + size = imem ? ucode_header[OS_CODE_SIZE] : ucode_header[OS_DATA_SIZE]; + + for (i = 0; i < size; i += NVGPU_DMA_CHUNK_SIZE) { + + /* Setup destination IMEM/DMEM offset */ + nvgpu_writel(g, nvgpu_safe_add_u32(flcn_base, falcon_falcon_dmatrfmoffs_r()), i); + + /* Setup source offset (relative to BASE) */ + nvgpu_writel(g, nvgpu_safe_add_u32(flcn_base, falcon_falcon_dmatrffboffs_r()), + nvgpu_safe_add_u32(offset, i)); + + nvgpu_writel(g, nvgpu_safe_add_u32(flcn_base, falcon_falcon_dmatrfcmd_r()), + falcon_falcon_dmatrfcmd_imem_f(imem) | + falcon_falcon_dmatrfcmd_write_f(0x00) | + falcon_falcon_dmatrfcmd_size_f(0x06) | + falcon_falcon_dmatrfcmd_ctxdma_f(UCODE_DMA_ID)); + + err = gk20a_falcon_dma_wait_idle(flcn); + if (err != 0) { + nvgpu_err(g, "falcon_dma_wait_idle failed err=%d", err); + return err; + } + } + + return 0; +} + +/* Load the ucode to IMEM and DMEM */ +s32 gk20a_falcon_load_ucode_dma(struct nvgpu_falcon *flcn, + struct nvgpu_mem *mem_desc, u32 *ucode_header) +{ + s32 err = 0; + struct gk20a *g = flcn->g; + u64 base_addr; + + /* Using the physical address for fw loading */ + base_addr = nvgpu_mem_get_phys_addr(g, mem_desc); + nvgpu_writel(g, nvgpu_safe_add_u32(flcn->flcn_base, falcon_falcon_dmactl_r()), 0); + nvgpu_writel(g, nvgpu_safe_add_u32(flcn->flcn_base, falcon_falcon_dmatrfbase_r()), + u64_lo32(base_addr >> 8)); + + /* Load the data segment to DMEM */ + err = gk20a_falcon_dma_ucode(flcn, ucode_header, false); + if (err != 0) { + nvgpu_err(g, "dmem loading failed err=%d", err); + return err; + } + + /* Load code segment to IMEM */ + err = gk20a_falcon_dma_ucode(flcn, ucode_header, true); + if (err != 0) { + nvgpu_err(g, "imem loading failed err=%d", err); + return err; + } + + return 0; +} diff --git a/drivers/gpu/nvgpu/hal/fifo/channel_gv11b_fusa.c b/drivers/gpu/nvgpu/hal/fifo/channel_gv11b_fusa.c index 7109541b7..46620cc6d 100644 --- a/drivers/gpu/nvgpu/hal/fifo/channel_gv11b_fusa.c +++ b/drivers/gpu/nvgpu/hal/fifo/channel_gv11b_fusa.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "channel_gk20a.h" #include "channel_gv11b.h" @@ -43,7 +44,8 @@ void gv11b_channel_bind(struct nvgpu_channel *ch) ch->chid, inst_ptr); /* Enable subcontext */ - if (g->ops.tsg.add_subctx_channel_hw != NULL) { + if ((g->ops.tsg.add_subctx_channel_hw != NULL) && + (!nvgpu_engine_is_multimedia_runlist_id(g, ch->runlist->id))) { err = g->ops.tsg.add_subctx_channel_hw(ch, ch->replayable); if (err != 0) { nvgpu_err(g, "Subcontext addition failed %d", err); diff --git a/drivers/gpu/nvgpu/hal/fifo/tsg_gv11b_fusa.c b/drivers/gpu/nvgpu/hal/fifo/tsg_gv11b_fusa.c index 6c6aa7739..ca10b03e6 100644 --- a/drivers/gpu/nvgpu/hal/fifo/tsg_gv11b_fusa.c +++ b/drivers/gpu/nvgpu/hal/fifo/tsg_gv11b_fusa.c @@ -36,6 +36,7 @@ /* can be removed after runque support is added */ #define GR_RUNQUE 0U /* pbdma 0 */ #define ASYNC_CE_RUNQUE 2U /* pbdma 2 */ +#define NVENC_RUNQUE 3U /* pbdma 3 */ /* TSG enable sequence applicable for Volta and onwards */ void gv11b_tsg_enable(struct nvgpu_tsg *tsg) @@ -99,6 +100,8 @@ void gv11b_tsg_bind_channel_eng_method_buffers(struct nvgpu_tsg *tsg, if (tsg->runlist->id == nvgpu_engine_get_fast_ce_runlist_id(g)) { gpu_va = tsg->eng_method_buffers[ASYNC_CE_RUNQUE].gpu_va; + } else if (tsg->runlist->id == nvgpu_engine_get_nvenc_runlist_id(g)) { + gpu_va = tsg->eng_method_buffers[NVENC_RUNQUE].gpu_va; } else { gpu_va = tsg->eng_method_buffers[GR_RUNQUE].gpu_va; } diff --git a/drivers/gpu/nvgpu/hal/init/hal_tu104.c b/drivers/gpu/nvgpu/hal/init/hal_tu104.c index a44d87061..80e1c5df0 100644 --- a/drivers/gpu/nvgpu/hal/init/hal_tu104.c +++ b/drivers/gpu/nvgpu/hal/init/hal_tu104.c @@ -171,6 +171,7 @@ #include "hal/pmu/pmu_tu104.h" #include "hal/falcon/falcon_gk20a.h" #include "hal/nvdec/nvdec_tu104.h" +#include "hal/nvenc/nvenc_tu104.h" #include "hal/gsp/gsp_tu104.h" #ifdef CONFIG_NVGPU_DEBUGGER #include "hal/perf/perf_gv11b.h" @@ -219,6 +220,7 @@ #include #include #include +#include #ifdef CONFIG_NVGPU_LS_PMU #include #endif @@ -787,6 +789,8 @@ static const struct gops_class tu104_ops_gpu_class = { #ifdef CONFIG_NVGPU_GRAPHICS .is_valid_gfx = tu104_class_is_valid_gfx, #endif + .is_valid_multimedia = tu104_class_is_valid_multimedia, + .is_valid_nvenc = tu104_class_is_valid_nvenc, }; static const struct gops_fb_ecc tu104_ops_fb_ecc = { @@ -876,6 +880,20 @@ static const struct gops_nvdec tu104_ops_nvdec = { .falcon_base_addr = tu104_nvdec_falcon_base_addr, }; +static const struct gops_nvenc tu104_ops_nvenc = { + .base_addr = tu104_nvenc_base_addr, + .init = nvgpu_nvenc_sw_init, + .deinit = nvgpu_nvenc_sw_deinit, + .setup_boot_config = tu104_nvenc_setup_boot_config, + .bootstrap = nvgpu_nvenc_falcon_boot, + .halt_engine = tu104_nvenc_halt_engine, + .reset = nvgpu_nvenc_reset, + .set_irq_regs = tu104_nvenc_set_irq_regs, + .interface_enable = tu104_nvenc_interface_enable, + .multimedia_alloc_ctx = nvgpu_multimedia_setup_ctx, + .multimedia_free_ctx = nvgpu_multimedia_free_ctx, +}; + static const struct gops_cg tu104_ops_cg = { .slcg_bus_load_gating_prod = tu104_slcg_bus_load_gating_prod, .slcg_ce2_load_gating_prod = tu104_slcg_ce2_load_gating_prod, @@ -1523,6 +1541,7 @@ static const struct gops_falcon tu104_ops_falcon = { .copy_from_imem = gk20a_falcon_copy_from_imem, .get_falcon_ctls = gk20a_falcon_get_ctls, #endif + .load_ucode = gk20a_falcon_load_ucode_dma, }; #endif @@ -1718,6 +1737,7 @@ int tu104_init_hal(struct gk20a *g) gops->fb.ecc = tu104_ops_fb_ecc; gops->fb.intr = tu104_ops_fb_intr; gops->nvdec = tu104_ops_nvdec; + gops->nvenc = tu104_ops_nvenc; gops->cg = tu104_ops_cg; gops->fifo = tu104_ops_fifo; gops->engine = tu104_ops_engine; diff --git a/drivers/gpu/nvgpu/hal/init/hal_tu104_litter.c b/drivers/gpu/nvgpu/hal/init/hal_tu104_litter.c index f3dc23db1..0e7603c2a 100644 --- a/drivers/gpu/nvgpu/hal/init/hal_tu104_litter.c +++ b/drivers/gpu/nvgpu/hal/init/hal_tu104_litter.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2022, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2019-2023, 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"), @@ -166,6 +166,9 @@ u32 tu104_get_litter_value(struct gk20a *g, int value) case GPU_LIT_DMA_COPY_CLASS: ret = TURING_DMA_COPY_A; break; + case GPU_LIT_NVENC_CLASS: + ret = TURING_NVENC_A; + break; #endif case GPU_LIT_GPC_PRIV_STRIDE: ret = proj_gpc_priv_stride_v(); diff --git a/drivers/gpu/nvgpu/hal/mc/mc_gv100.c b/drivers/gpu/nvgpu/hal/mc/mc_gv100.c index 7763ce7fc..412cedf60 100644 --- a/drivers/gpu/nvgpu/hal/mc/mc_gv100.c +++ b/drivers/gpu/nvgpu/hal/mc/mc_gv100.c @@ -1,7 +1,7 @@ /* * GV100 master * - * Copyright (c) 2016-2021, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2016-2023, 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"), @@ -88,6 +88,9 @@ static u32 gv100_mc_unit_reset_mask(struct gk20a *g, u32 unit) case NVGPU_UNIT_NVDEC: mask = mc_enable_nvdec_enabled_f(); break; + case NVGPU_UNIT_NVENC: + mask = mc_enable_nvenc_enabled_f(); + break; case NVGPU_UNIT_NVLINK: mask = BIT32(g->nvlink.ioctrl_table[0].reset_enum); break; @@ -144,5 +147,6 @@ int gv100_mc_enable_units(struct gk20a *g, u32 units, bool enable) (enable ? "enable" : "disable"), mask); return -EINVAL; } + return 0U; } diff --git a/drivers/gpu/nvgpu/hal/mc/mc_tu104.c b/drivers/gpu/nvgpu/hal/mc/mc_tu104.c index b74ffd02e..ac7323574 100644 --- a/drivers/gpu/nvgpu/hal/mc/mc_tu104.c +++ b/drivers/gpu/nvgpu/hal/mc/mc_tu104.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2022, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2018-2023, 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"), @@ -223,6 +223,9 @@ static u32 intr_tu104_intr_pending_f(struct gk20a *g, u32 unit) case NVGPU_CIC_INTR_UNIT_FBPA: intr_pending_f = mc_intr_pfb_pending_f(); break; + case NVGPU_CIC_INTR_UNIT_NVENC: + intr_pending_f = mc_intr_nvenc0_pending_f(); + break; default: nvgpu_err(g, "Invalid MC interrupt unit specified !!!"); break; diff --git a/drivers/gpu/nvgpu/hal/nvenc/nvenc_tu104.c b/drivers/gpu/nvgpu/hal/nvenc/nvenc_tu104.c new file mode 100644 index 000000000..f701023b9 --- /dev/null +++ b/drivers/gpu/nvgpu/hal/nvenc/nvenc_tu104.c @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2023, 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 "nvenc_tu104.h" +#include + +u32 tu104_nvenc_base_addr(void) +{ + return pnvenc_falcon_irqsset_r(0); +} + +void tu104_nvenc_setup_boot_config(struct gk20a *g) +{ + u32 data = 0; + + data = nvgpu_readl(g, pnvenc_fbif_ctl_r()); + data |= pnvenc_fbif_ctl_allow_phys_no_ctx_allow_f(); + nvgpu_writel(g, pnvenc_fbif_ctl_r(), data); + + /* Setup aperture (physical) for ucode loading */ + data = nvgpu_readl(g, pnvenc_fbif_transcfg_r(UCODE_DMA_ID)); + data |= pnvenc_fbif_transcfg_mem_type_physical_f() | + pnvenc_fbif_transcfg_target_noncoherent_sysmem_f(); + nvgpu_writel(g, pnvenc_fbif_transcfg_r(UCODE_DMA_ID), data); + + /* Enable the context interface */ + nvgpu_writel(g, pnvenc_falcon_itfen_r(), + nvgpu_readl(g, pnvenc_falcon_itfen_r()) | + pnvenc_falcon_itfen_ctxen_enable_f()); +} + +void tu104_nvenc_halt_engine(struct gk20a *g) +{ + u32 data; + + data = nvgpu_readl(g, pnvenc_falcon_engctl_r()); + data |= pnvenc_falcon_engctl_stallreq_true_f(); + nvgpu_writel(g, pnvenc_falcon_engctl_r(), data); + + data = nvgpu_readl(g, pnvenc_falcon_engctl_r()); + if (pnvenc_falcon_engctl_stallack_v(data) == 0U) { + nvgpu_err(g, "NVENC engine is not idle while reset"); + } +} + +void tu104_nvenc_set_irq_regs(struct gk20a *g, struct nvgpu_falcon *flcn) +{ + u32 intr_mask; + u32 intr_dest; + + /* dest 0=falcon, 1=host; level 0=irq0, 1=irq1 */ + intr_dest = pnvenc_falcon_irqdest_host_gptmr_f(0) | + pnvenc_falcon_irqdest_host_wdtmr_f(1) | + pnvenc_falcon_irqdest_host_mthd_f(0) | + pnvenc_falcon_irqdest_host_ctxsw_f(0) | + pnvenc_falcon_irqdest_host_halt_f(1) | + pnvenc_falcon_irqdest_host_exterr_f(1) | + pnvenc_falcon_irqdest_host_swgen0_f(1) | + pnvenc_falcon_irqdest_host_swgen1_f(1) | + pnvenc_falcon_irqdest_host_ext_f(0xff) | + pnvenc_falcon_irqdest_target_gptmr_f(0) | + pnvenc_falcon_irqdest_target_wdtmr_f(0) | + pnvenc_falcon_irqdest_target_mthd_f(0) | + pnvenc_falcon_irqdest_target_ctxsw_f(0) | + pnvenc_falcon_irqdest_target_halt_f(0) | + pnvenc_falcon_irqdest_target_exterr_f(0) | + pnvenc_falcon_irqdest_target_swgen0_f(0) | + pnvenc_falcon_irqdest_target_swgen1_f(0) | + pnvenc_falcon_irqdest_target_ext_f(0); + + /* 0=disable, 1=enable */ + intr_mask = pnvenc_falcon_irqmset_gptmr_f(0) | + pnvenc_falcon_irqmset_wdtmr_f(1) | + pnvenc_falcon_irqmset_mthd_f(0) | + pnvenc_falcon_irqmset_ctxsw_f(0) | + pnvenc_falcon_irqmset_halt_f(1) | + pnvenc_falcon_irqmset_exterr_f(0) | + pnvenc_falcon_irqmset_swgen0_f(1) | + pnvenc_falcon_irqmset_swgen1_f(1) | + pnvenc_falcon_irqmset_ext_f(0xff); + + g->ops.falcon.set_irq(flcn, true, intr_mask, intr_dest); +} + +void tu104_nvenc_interface_enable(struct gk20a *g) +{ + u32 itfen; + + itfen = nvgpu_readl(g, pnvenc_falcon_itfen_r()) | + pnvenc_falcon_itfen_ctxen_enable_f() | + pnvenc_falcon_itfen_mthden_enable_f(); + nvgpu_writel(g, pnvenc_falcon_itfen_r(), itfen); +} diff --git a/drivers/gpu/nvgpu/hal/nvenc/nvenc_tu104.h b/drivers/gpu/nvgpu/hal/nvenc/nvenc_tu104.h new file mode 100644 index 000000000..6f41641d1 --- /dev/null +++ b/drivers/gpu/nvgpu/hal/nvenc/nvenc_tu104.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2023, 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_NVENC_TU104_H +#define NVGPU_NVENC_TU104_H + +#include + +struct gk20a; + +u32 tu104_nvenc_base_addr(void); +void tu104_nvenc_setup_boot_config(struct gk20a *g); +void tu104_nvenc_halt_engine(struct gk20a *g); +void tu104_nvenc_set_irq_regs(struct gk20a *g, struct nvgpu_falcon *flcn); +void tu104_nvenc_interface_enable(struct gk20a *g); + +#endif /* NVGPU_NVENC_TU104_H */ diff --git a/drivers/gpu/nvgpu/include/nvgpu/cic_mon.h b/drivers/gpu/nvgpu/include/nvgpu/cic_mon.h index 1bc6ec417..f0446fc5f 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/cic_mon.h +++ b/drivers/gpu/nvgpu/include/nvgpu/cic_mon.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2021-2023, 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"), @@ -226,6 +226,11 @@ struct nvgpu_err_desc; * CIC interrupt for FBPA unit. */ #define NVGPU_CIC_INTR_UNIT_FBPA 9 +/** + * @ingroup NVGPU_CIC_INTR_UNIT_DEFINES + * CIC interrupt for NVENC unit. + */ +#define NVGPU_CIC_INTR_UNIT_NVENC 10 /** * @defgroup NVGPU_CIC_INTR_ENABLE_DEFINES @@ -413,7 +418,7 @@ int nvgpu_cic_mon_get_num_hw_modules(struct gk20a *g); /** * @brief Fatal error interrupt handler for safety. * - * @param g [in] The GPU driver struct. + * @param g [in] The GPU driver struct. * * This function is invoked by NVGPU_MON_DEVCTL_NOTIFY_INTR devctl raised by nvgpu-mon. * It is called to parse the interrupt tree and determine exact error. diff --git a/drivers/gpu/nvgpu/include/nvgpu/class.h b/drivers/gpu/nvgpu/include/nvgpu/class.h index 844f3a536..40b0d6d6f 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/class.h +++ b/drivers/gpu/nvgpu/include/nvgpu/class.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2021, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2019-2023, 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"), @@ -90,6 +90,7 @@ #define TURING_CHANNEL_GPFIFO_A 0xC46FU #define TURING_COMPUTE_A 0xC5C0U #define TURING_DMA_COPY_A 0xC5B5U +#define TURING_NVENC_A 0xC4B7U #define AMPERE_SMC_PARTITION_REF 0xC637U #define AMPERE_B 0xC797U diff --git a/drivers/gpu/nvgpu/include/nvgpu/enabled.h b/drivers/gpu/nvgpu/include/nvgpu/enabled.h index cc2afc31b..61c30a273 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/enabled.h +++ b/drivers/gpu/nvgpu/include/nvgpu/enabled.h @@ -239,6 +239,8 @@ struct gk20a; "To enable kmd sheduling worker thread"), \ DEFINE_FLAG(NVGPU_SUPPORT_MULTI_PROCESS_TSG_SHARING, \ "Multi process TSG sharing support"), \ + DEFINE_FLAG(NVGPU_SUPPORT_MULTIMEDIA, \ + "Multimedia engine support"), \ DEFINE_FLAG(NVGPU_MAX_ENABLED_BITS, "Marks max number of flags"), /** diff --git a/drivers/gpu/nvgpu/include/nvgpu/engines.h b/drivers/gpu/nvgpu/include/nvgpu/engines.h index b634da312..39d49d8f1 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/engines.h +++ b/drivers/gpu/nvgpu/include/nvgpu/engines.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2021, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2019-2023, 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"), @@ -61,8 +61,10 @@ enum nvgpu_fifo_engine { NVGPU_ENGINE_GRCE = 1U, /** Async CE engine enum */ NVGPU_ENGINE_ASYNC_CE = 2U, + /** NVENC engine enum */ + NVGPU_ENGINE_NVENC = 3U, /** Invalid engine enum */ - NVGPU_ENGINE_INVAL = 3U, + NVGPU_ENGINE_INVAL = 4U, }; /** @@ -273,6 +275,23 @@ u32 nvgpu_engine_get_fast_ce_runlist_id(struct gk20a *g); * gr h/w engine id is NULL. */ u32 nvgpu_engine_get_gr_runlist_id(struct gk20a *g); +/** + * @brief Get runlist id for the first available #NVGPU_ENGINE_NVENC engine enum + * type. + * + * @param g [in] The GPU driver struct. + * + * - Get h/w engine id for the first available #NVGPU_ENGINE_NVENC engine enum + * type. + * -- Get #nvgpu_engine_info for the first available nvenc engine id. + * -- Get #nvgpu_engine_info.runlist_id for first available nvenc engine id. + * + * @return #nvgpu_engine_info.runlist_id for the first available nvenc engine id. + * @retval U32_MAX if #NVGPU_ENGINE_NVENC engine enum type is not available. + * @retval U32_MAX if pointer to #nvgpu_engine_info for the first available + * nvenc h/w engine id is NULL. + */ +u32 nvgpu_engine_get_nvenc_runlist_id(struct gk20a *g); /** * @brief Check if runlist id corresponds to runlist id of one of the * engine ids supported by h/w. @@ -290,6 +309,23 @@ u32 nvgpu_engine_get_gr_runlist_id(struct gk20a *g); * any of the runlist ids of engine ids supported by h/w. */ bool nvgpu_engine_is_valid_runlist_id(struct gk20a *g, u32 runlist_id); +/** + * @brief Check if the given runlist id belongs to one of the multimedia engines + * supported by the h/w. + * + * @param g [in] The GPU driver struct. + * @param runlist_id [in] Runlist id. + * + * Check if #runlist_id corresponds to runlist id of one of the multimedia engines + * supported by h/w, by checking #nvgpu_engine_info for each of the supported + * multimedia engines in #nvgpu_fifo.num_engines engines. + * + * @return True if #runlist_id is valid. + * @return False if #nvgpu_engine_info is NULL for all multimedia engines starting + * with 0 up to #nvgpu_fifo.num_engines or #runlist_id did not match with + * any of the runlist ids of multimedia engine ids supported by h/w. + */ +bool nvgpu_engine_is_multimedia_runlist_id(struct gk20a *g, u32 runlist_id); /** * @brief Get mmu fault id for the engine id. * diff --git a/drivers/gpu/nvgpu/include/nvgpu/falcon.h b/drivers/gpu/nvgpu/include/nvgpu/falcon.h index db1475945..ae83bdf59 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/falcon.h +++ b/drivers/gpu/nvgpu/include/nvgpu/falcon.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2022, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2017-2023, 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"), @@ -126,6 +126,8 @@ #define FALCON_ID_GPCCS (3U) /** Falcon ID for NVDEC engine */ #define FALCON_ID_NVDEC (4U) +/** Falcon ID for NVDEC engine */ +#define FALCON_ID_NVENC (5U) /** Falcon ID for SEC2 engine */ #define FALCON_ID_SEC2 (7U) /** Falcon ID for MINION engine */ @@ -199,6 +201,7 @@ struct gk20a; struct nvgpu_falcon; +struct nvgpu_mem; /** * Falcon memory types. @@ -722,6 +725,8 @@ int nvgpu_falcon_copy_from_emem(struct nvgpu_falcon *flcn, u32 src, u8 *dst, u32 size, u8 port); int nvgpu_falcon_copy_to_emem(struct nvgpu_falcon *flcn, u32 dst, u8 *src, u32 size, u8 port); +s32 nvgpu_falcon_load_ucode(struct nvgpu_falcon *flcn, + struct nvgpu_mem *ucode_mem_desc, u32 *ucode_header); #ifdef CONFIG_NVGPU_FALCON_DEBUG void nvgpu_falcon_dump_stats(struct nvgpu_falcon *flcn); diff --git a/drivers/gpu/nvgpu/include/nvgpu/gk20a.h b/drivers/gpu/nvgpu/include/nvgpu/gk20a.h index c34c37b94..325d01e44 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/gk20a.h +++ b/drivers/gpu/nvgpu/include/nvgpu/gk20a.h @@ -129,7 +129,7 @@ struct nvgpu_gsp_sched; #ifdef CONFIG_NVGPU_GSP_STRESS_TEST struct nvgpu_gsp_test; #endif - +struct nvgpu_nvenc; #ifdef CONFIG_NVGPU_DGPU enum nvgpu_nvlink_minion_dlcmd; #endif @@ -167,6 +167,7 @@ enum nvgpu_profiler_pm_reservation_scope; #include #include #include +#include #include @@ -301,6 +302,8 @@ struct railgate_stats { #define GPU_LIT_ROP_IN_GPC_STRIDE 55 #define GPU_LIT_PERFMON_PMMGPC_ROP_DOMAIN_START 56 #define GPU_LIT_PERFMON_PMMGPC_ROP_DOMAIN_COUNT 57 +/** NVENC class. */ +#define GPU_LIT_NVENC_CLASS 58 /** Macro to get litter values corresponding to the litter defines. */ #define nvgpu_get_litter_value(g, v) ((g)->ops.get_litter_value((g), v)) @@ -503,6 +506,8 @@ struct gk20a { struct nvgpu_falcon fecs_flcn; /** Struct holding the gpccs falcon software state. */ struct nvgpu_falcon gpccs_flcn; + /** Struct holding the nvenc falcon software state. */ + struct nvgpu_falcon nvenc_flcn; #ifdef CONFIG_NVGPU_DGPU struct nvgpu_falcon nvdec_flcn; struct nvgpu_falcon minion_flcn; @@ -556,6 +561,7 @@ struct gk20a { #endif /** Top level struct maintaining ECC unit's software state. */ struct nvgpu_ecc ecc; + struct nvgpu_nvenc *nvenc; #ifdef CONFIG_NVGPU_DGPU struct pmgr_pmupstate *pmgr_pmu; struct nvgpu_sec2 sec2; diff --git a/drivers/gpu/nvgpu/include/nvgpu/gops/class.h b/drivers/gpu/nvgpu/include/nvgpu/gops/class.h index ca9383259..bbfe35a50 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/gops/class.h +++ b/drivers/gpu/nvgpu/include/nvgpu/gops/class.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2021, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2019-2023, 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"), @@ -51,6 +51,8 @@ struct gops_class { * - \ref #VOLTA_CHANNEL_GPFIFO_A -> 0xC36FU * 4. Graphics class: * - \ref #VOLTA_A -> 0xC397U + * 5. NVENC class: + * - \ref #TURING_NVENC_A -> 0xC4B7U * * @param class_num [in] Class number to be validated based on * GPU architecture. @@ -86,6 +88,39 @@ struct gops_class { #ifdef CONFIG_NVGPU_GRAPHICS bool (*is_valid_gfx)(u32 class_num); #endif + /** + * @brief Checks if given class number is valid multimedia class number + * as per our GPU architecture. + * + * List of valid multimedia class numbers: + * - \ref #TURING_NVENC_A -> 0xC4B7U + * + * @param class_num [in] Class number to be validated based on + * GPU architecture. + * - No validation is performed on this + * parameter + * + * @return true when \a class_num is one of the numbers in above list or + * false otherwise. + */ + bool (*is_valid_multimedia)(u32 class_num); + + /** + * @brief Checks if given class number is valid nvenc class number + * as per our GPU architecture. + * + * List of valid nvenc class numbers: + * - \ref #TURING_NVENC_A -> 0xC4B7U + * + * @param class_num [in] Class number to be validated based on + * GPU architecture. + * - No validation is performed on this + * parameter + * + * @return true when \a class_num is one of the numbers in above list or + * false otherwise. + */ + bool (*is_valid_nvenc)(u32 class_num); /** @endcond DOXYGEN_SHOULD_SKIP_THIS */ }; diff --git a/drivers/gpu/nvgpu/include/nvgpu/gops/falcon.h b/drivers/gpu/nvgpu/include/nvgpu/gops/falcon.h index 7d476e4e0..3171466ff 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/gops/falcon.h +++ b/drivers/gpu/nvgpu/include/nvgpu/gops/falcon.h @@ -84,6 +84,9 @@ struct gops_falcon { u32 *sctl, u32 *cpuctl); #endif + int (*load_ucode)(struct nvgpu_falcon *flcn, + struct nvgpu_mem *mem_desc, u32 *ucode_header); + /** @endcond DOXYGEN_SHOULD_SKIP_THIS */ }; diff --git a/drivers/gpu/nvgpu/include/nvgpu/gops/nvenc.h b/drivers/gpu/nvgpu/include/nvgpu/gops/nvenc.h new file mode 100644 index 000000000..2e0150d02 --- /dev/null +++ b/drivers/gpu/nvgpu/include/nvgpu/gops/nvenc.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2023, 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_GOPS_NVENC_H +#define NVGPU_GOPS_NVENC_H + +struct nvgpu_multimedia_ctx; + +struct gops_nvenc { + + u32 (*base_addr)(void); + /** + * Initializes nvenc unit private data struct in the GPU driver based on + * the current chip. + */ + int (*init)(struct gk20a *g); + + /** + * @brief Deinitialize NVENC support. + * + * @param g [in] Pointer to GPU driver struct. + * + * This function de-allocates memory allocated during initialization. + */ + int (*deinit)(struct gk20a *g); + + /** + * @brief Reset NVENC. + * + * @param g [in] Pointer to GPU driver struct. + * + * This function resets the NVENC HW unit and loads the FW again. + */ + int (*reset)(struct gk20a *g); + + /** + * Load and bootstrap ucode on nvenc falcon. + */ + int (*bootstrap)(struct gk20a *g); + void (*setup_boot_config)(struct gk20a *g); + void (*halt_engine)(struct gk20a *g); + void (*set_irq_regs)(struct gk20a *g, struct nvgpu_falcon *flcn); + void (*interface_enable)(struct gk20a *g); + + /** + * @brief Allocate and setup engine context for GPU channel. + * + * @param ch [in] Pointer to GPU channel. + * @param class_num [in] GPU class ID. + * @param flags [in] Flags for context allocation. + * + * This HAL allocates and sets up engine context for + * a GPU channel. + * + * @return 0 in case of success, < 0 in case of failure. + * @retval -ENOMEM if memory allocation for context buffer fails. + * @retval -EINVAL if invalid GPU class ID is provided. + */ + int (*multimedia_alloc_ctx)(struct nvgpu_channel *ch, + u32 class_num, u32 flags); + + /** + * @brief Free engine context buffer. + * + * @param g [in] Pointer to GPU driver struct. + * @param eng_ctx [in] Pointer to engine context data. + * + * This function will free the memory allocated for engine + * context buffer. + */ + void (*multimedia_free_ctx)(struct gk20a *g, + struct nvgpu_multimedia_ctx *eng_ctx); +}; + +#endif /* NVGPU_GOPS_NVENC_H */ diff --git a/drivers/gpu/nvgpu/include/nvgpu/gpu_ops.h b/drivers/gpu/nvgpu/include/nvgpu/gpu_ops.h index 809a5d91e..e3e4feb82 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/gpu_ops.h +++ b/drivers/gpu/nvgpu/include/nvgpu/gpu_ops.h @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -238,6 +239,7 @@ struct gpu_ops { struct gops_sbr sbr; struct gops_func func; struct gops_nvdec nvdec; + struct gops_nvenc nvenc; struct gops_ramfc ramfc; struct gops_ramin ramin; struct gops_userd userd; diff --git a/drivers/gpu/nvgpu/include/nvgpu/hw/gm20b/hw_falcon_gm20b.h b/drivers/gpu/nvgpu/include/nvgpu/hw/gm20b/hw_falcon_gm20b.h index ec154ac42..39e1b87e1 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/hw/gm20b/hw_falcon_gm20b.h +++ b/drivers/gpu/nvgpu/include/nvgpu/hw/gm20b/hw_falcon_gm20b.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2017-2023, 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"), @@ -161,6 +161,7 @@ #define falcon_falcon_dmatrfcmd_write_f(v) ((U32(v) & 0x1U) << 5U) #define falcon_falcon_dmatrfcmd_size_f(v) ((U32(v) & 0x7U) << 8U) #define falcon_falcon_dmatrfcmd_ctxdma_f(v) ((U32(v) & 0x7U) << 12U) +#define falcon_falcon_dmatrfcmd_idle_v(r) (((r) >> 1U) & 0x1U) #define falcon_falcon_dmatrffboffs_r() (0x0000011cU) #define falcon_falcon_imctl_debug_r() (0x0000015cU) #define falcon_falcon_imctl_debug_addr_blk_f(v) ((U32(v) & 0xffffffU) << 0U) diff --git a/drivers/gpu/nvgpu/include/nvgpu/hw/gv100/hw_mc_gv100.h b/drivers/gpu/nvgpu/include/nvgpu/hw/gv100/hw_mc_gv100.h index db192547a..68d858902 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/hw/gv100/hw_mc_gv100.h +++ b/drivers/gpu/nvgpu/include/nvgpu/hw/gv100/hw_mc_gv100.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2017-2023, 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"), @@ -74,6 +74,7 @@ #define mc_intr_priv_ring_pending_f() (0x40000000U) #define mc_intr_pbus_pending_f() (0x10000000U) #define mc_intr_nvlink_pending_f() (0x400000U) +#define mc_intr_nvenc0_pending_f() (0x10000U) #define mc_intr_en_r(i)\ (nvgpu_safe_add_u32(0x00000140U, nvgpu_safe_mult_u32((i), 4U))) #define mc_intr_en_set_r(i)\ @@ -101,6 +102,8 @@ #define mc_enable_hub_enabled_f() (0x20000000U) #define mc_enable_nvdec_disabled_v() (0x00000000U) #define mc_enable_nvdec_enabled_f() (0x8000U) +#define mc_enable_nvenc_disabled_v() (0x00000000U) +#define mc_enable_nvenc_enabled_f() (0x40000U) #define mc_enable_nvlink_disabled_v() (0x00000000U) #define mc_enable_nvlink_disabled_f() (0x0U) #define mc_enable_nvlink_enabled_v() (0x00000001U) diff --git a/drivers/gpu/nvgpu/include/nvgpu/hw/tu104/hw_mc_tu104.h b/drivers/gpu/nvgpu/include/nvgpu/hw/tu104/hw_mc_tu104.h index 1a26197fd..d84fd3bf8 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/hw/tu104/hw_mc_tu104.h +++ b/drivers/gpu/nvgpu/include/nvgpu/hw/tu104/hw_mc_tu104.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2018-2023, 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"), @@ -75,6 +75,7 @@ #define mc_intr_priv_ring_pending_f() (0x40000000U) #define mc_intr_pbus_pending_f() (0x10000000U) #define mc_intr_nvlink_pending_f() (0x400000U) +#define mc_intr_nvenc0_pending_f() (0x10000U) #define mc_intr_en_r(i)\ (nvgpu_safe_add_u32(0x00000140U, nvgpu_safe_mult_u32((i), 4U))) #define mc_intr_en_set_r(i)\ @@ -98,6 +99,8 @@ #define mc_enable_perfmon_enabled_f() (0x10000000U) #define mc_enable_nvdec_disabled_v() (0x00000000U) #define mc_enable_nvdec_enabled_f() (0x8000U) +#define mc_enable_nvenc_disabled_v() (0x00000000U) +#define mc_enable_nvenc_enabled_f() (0x40000U) #define mc_enable_nvlink_disabled_v() (0x00000000U) #define mc_enable_nvlink_disabled_f() (0x0U) #define mc_enable_nvlink_enabled_v() (0x00000001U) diff --git a/drivers/gpu/nvgpu/include/nvgpu/hw/tu104/hw_pnvenc_tu104.h b/drivers/gpu/nvgpu/include/nvgpu/hw/tu104/hw_pnvenc_tu104.h new file mode 100644 index 000000000..1bc3a490c --- /dev/null +++ b/drivers/gpu/nvgpu/include/nvgpu/hw/tu104/hw_pnvenc_tu104.h @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2023, 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. + */ +/* + * Function/Macro naming determines intended use: + * + * _r(void) : Returns the offset for register . + * + * _o(void) : Returns the offset for element . + * + * _w(void) : Returns the word offset for word (4 byte) element . + * + * __s(void) : Returns size of field of register in bits. + * + * __f(u32 v) : Returns a value based on 'v' which has been shifted + * and masked to place it at field of register . This value + * can be |'d with others to produce a full register value for + * register . + * + * __m(void) : Returns a mask for field of register . This + * value can be ~'d and then &'d to clear the value of field for + * register . + * + * ___f(void) : Returns the constant value after being shifted + * to place it at field of register . This value can be |'d + * with others to produce a full register value for . + * + * __v(u32 r) : Returns the value of field from a full register + * value 'r' after being shifted to place its LSB at bit 0. + * This value is suitable for direct comparison with other unshifted + * values appropriate for use in field of register . + * + * ___v(void) : Returns the constant value for defined for + * field of register . This value is suitable for direct + * comparison with unshifted values appropriate for use in field + * of register . + */ +#ifndef NVGPU_HW_PNVENC_TU104_H +#define NVGPU_HW_PNVENC_TU104_H + +#include +#include + +#define pnvenc_falcon_irqsset_r(i)\ + (nvgpu_safe_add_u32(0x001c8000U, nvgpu_safe_mult_u32((i), 16384U))) +#define pnvenc_falcon_itfen_r() (0x001c8048U) +#define pnvenc_falcon_itfen_ctxen_enable_f() (0x1U) +#define pnvenc_falcon_itfen_mthden_enable_f() (0x2U) +#define pnvenc_falcon_engctl_r() (0x001c80a4U) +#define pnvenc_falcon_engctl_stallreq_true_f() (0x100U) +#define pnvenc_falcon_engctl_stallack_v(r) (((r) >> 9U) & 0x1U) +#define pnvenc_falcon_engctl_stallack_true_f() (0x200U) +#define pnvenc_fbif_transcfg_r(i)\ + (nvgpu_safe_add_u32(0x001c8800U, nvgpu_safe_mult_u32((i), 4U))) +#define pnvenc_fbif_transcfg_target_local_fb_f() (0x0U) +#define pnvenc_fbif_transcfg_target_coherent_sysmem_f() (0x1U) +#define pnvenc_fbif_transcfg_target_noncoherent_sysmem_f() (0x2U) +#define pnvenc_fbif_transcfg_mem_type_s() (1U) +#define pnvenc_fbif_transcfg_mem_type_f(v) ((U32(v) & 0x1U) << 2U) +#define pnvenc_fbif_transcfg_mem_type_m() (U32(0x1U) << 2U) +#define pnvenc_fbif_transcfg_mem_type_v(r) (((r) >> 2U) & 0x1U) +#define pnvenc_fbif_transcfg_mem_type_virtual_f() (0x0U) +#define pnvenc_fbif_transcfg_mem_type_physical_f() (0x4U) +#define pnvenc_fbif_ctl_r() (0x001c8824U) +#define pnvenc_fbif_ctl_allow_phys_no_ctx_init_f() (0x0U) +#define pnvenc_fbif_ctl_allow_phys_no_ctx_disallow_f() (0x0U) +#define pnvenc_fbif_ctl_allow_phys_no_ctx_allow_f() (0x80U) +#define pnvenc_falcon_irqmset_r() (0x001c8010U) +#define pnvenc_falcon_irqmset_gptmr_f(v) ((U32(v) & 0x1U) << 0U) +#define pnvenc_falcon_irqmset_wdtmr_f(v) ((U32(v) & 0x1U) << 1U) +#define pnvenc_falcon_irqmset_mthd_f(v) ((U32(v) & 0x1U) << 2U) +#define pnvenc_falcon_irqmset_ctxsw_f(v) ((U32(v) & 0x1U) << 3U) +#define pnvenc_falcon_irqmset_halt_f(v) ((U32(v) & 0x1U) << 4U) +#define pnvenc_falcon_irqmset_exterr_f(v) ((U32(v) & 0x1U) << 5U) +#define pnvenc_falcon_irqmset_swgen0_f(v) ((U32(v) & 0x1U) << 6U) +#define pnvenc_falcon_irqmset_swgen1_f(v) ((U32(v) & 0x1U) << 7U) +#define pnvenc_falcon_irqmset_ext_f(v) ((U32(v) & 0xffU) << 8U) +#define pnvenc_falcon_irqdest_r() (0x001c801cU) +#define pnvenc_falcon_irqdest_host_gptmr_f(v) ((U32(v) & 0x1U) << 0U) +#define pnvenc_falcon_irqdest_host_wdtmr_f(v) ((U32(v) & 0x1U) << 1U) +#define pnvenc_falcon_irqdest_host_mthd_f(v) ((U32(v) & 0x1U) << 2U) +#define pnvenc_falcon_irqdest_host_ctxsw_f(v) ((U32(v) & 0x1U) << 3U) +#define pnvenc_falcon_irqdest_host_halt_f(v) ((U32(v) & 0x1U) << 4U) +#define pnvenc_falcon_irqdest_host_exterr_f(v) ((U32(v) & 0x1U) << 5U) +#define pnvenc_falcon_irqdest_host_swgen0_f(v) ((U32(v) & 0x1U) << 6U) +#define pnvenc_falcon_irqdest_host_swgen1_f(v) ((U32(v) & 0x1U) << 7U) +#define pnvenc_falcon_irqdest_host_ext_f(v) ((U32(v) & 0xffU) << 8U) +#define pnvenc_falcon_irqdest_target_gptmr_f(v) ((U32(v) & 0x1U) << 16U) +#define pnvenc_falcon_irqdest_target_wdtmr_f(v) ((U32(v) & 0x1U) << 17U) +#define pnvenc_falcon_irqdest_target_mthd_f(v) ((U32(v) & 0x1U) << 18U) +#define pnvenc_falcon_irqdest_target_ctxsw_f(v) ((U32(v) & 0x1U) << 19U) +#define pnvenc_falcon_irqdest_target_halt_f(v) ((U32(v) & 0x1U) << 20U) +#define pnvenc_falcon_irqdest_target_exterr_f(v) ((U32(v) & 0x1U) << 21U) +#define pnvenc_falcon_irqdest_target_swgen0_f(v) ((U32(v) & 0x1U) << 22U) +#define pnvenc_falcon_irqdest_target_swgen1_f(v) ((U32(v) & 0x1U) << 23U) +#define pnvenc_falcon_irqdest_target_ext_f(v) ((U32(v) & 0xffU) << 24U) +#endif diff --git a/drivers/gpu/nvgpu/include/nvgpu/list.h b/drivers/gpu/nvgpu/include/nvgpu/list.h index 2c4c73e8a..dd000d837 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/list.h +++ b/drivers/gpu/nvgpu/include/nvgpu/list.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2022, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2017-2023, 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"), @@ -266,9 +266,9 @@ static inline void nvgpu_list_replace_init(struct nvgpu_list_node *old_node, * @param type [in] Type of the entry. * @param member [in] Name of the list entry in \a type. */ -#define nvgpu_list_for_each_entry(pos, head, type, member) \ +#define nvgpu_list_for_each_entry(pos, head, type, member) \ for ((pos) = nvgpu_list_first_entry(head, type, member); \ - &(pos)->member != (head); \ + ((pos) != NULL) && (&(pos)->member != (head)); \ (pos) = nvgpu_list_next_entry(pos, type, member)) /** diff --git a/drivers/gpu/nvgpu/include/nvgpu/mc.h b/drivers/gpu/nvgpu/include/nvgpu/mc.h index cfa54975d..422f7462a 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/mc.h +++ b/drivers/gpu/nvgpu/include/nvgpu/mc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2021, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2018-2023, 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"), @@ -153,6 +153,8 @@ struct nvgpu_device; #define NVGPU_UNIT_CE2 BIT32(6) /** NVLINK unit */ #define NVGPU_UNIT_NVLINK BIT32(7) +/** NVENC unit */ +#define NVGPU_UNIT_NVENC BIT32(8) /** Bit offset of the Architecture field in the HW version register */ #define NVGPU_GPU_ARCHITECTURE_SHIFT 4U diff --git a/drivers/gpu/nvgpu/include/nvgpu/multimedia.h b/drivers/gpu/nvgpu/include/nvgpu/multimedia.h new file mode 100644 index 000000000..09d3ecfd1 --- /dev/null +++ b/drivers/gpu/nvgpu/include/nvgpu/multimedia.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2023, 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_MULTIMEDIA_H +#define NVGPU_MULTIMEDIA_H + +#include + +#define UCODE_DMA_ID (0x6) + +struct nvgpu_tsg; +struct vm_gk20a; +struct nvgpu_channel; + +/** + * Multimedia engine enum types supported from driver. + */ +enum nvgpu_multimedia_engine { + /** NVENC engine enum */ + NVGPU_MULTIMEDIA_ENGINE_NVENC = 0U, + /** Invalid engine enum */ + NVGPU_MULTIMEDIA_ENGINE_MAX +}; + +/** + * Multimedia engine context data structure. + */ +struct nvgpu_multimedia_ctx { + + /** Memory to hold context buffer */ + struct nvgpu_mem ctx_mem; + + /** TSG associated with this context */ + struct nvgpu_tsg *tsg; + + /** TSG identifier corresponding to this context */ + u32 tsgid; + + /** Context buffer initialised? */ + bool ctx_initialized; + +}; + +int nvgpu_multimedia_setup_ctx(struct nvgpu_channel *ch, u32 class_num, u32 flags); +void nvgpu_multimedia_free_ctx(struct gk20a *g, struct nvgpu_multimedia_ctx *eng_ctx); +void nvgpu_multimedia_free_all_ctx(struct nvgpu_tsg *tsg); +#endif diff --git a/drivers/gpu/nvgpu/include/nvgpu/nvenc.h b/drivers/gpu/nvgpu/include/nvgpu/nvenc.h new file mode 100644 index 000000000..bcba226ab --- /dev/null +++ b/drivers/gpu/nvgpu/include/nvgpu/nvenc.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2023, 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_NVENC_H +#define NVGPU_NVENC_H + +struct gk20a; + +int nvgpu_nvenc_falcon_boot(struct gk20a *g); +int nvgpu_nvenc_sw_init(struct gk20a *g); +int nvgpu_nvenc_sw_deinit(struct gk20a *g); +int nvgpu_nvenc_reset(struct gk20a *g); + +#endif diff --git a/drivers/gpu/nvgpu/include/nvgpu/tsg.h b/drivers/gpu/nvgpu/include/nvgpu/tsg.h index 40c4a7ed4..f980c6543 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/tsg.h +++ b/drivers/gpu/nvgpu/include/nvgpu/tsg.h @@ -32,6 +32,7 @@ #include #include #include +#include /** * Software defined invalid TSG id value. @@ -52,6 +53,7 @@ struct gk20a; struct nvgpu_channel; struct nvgpu_gr_ctx; +struct nvgpu_multimedia_ctx; struct nvgpu_channel_hw_state; struct nvgpu_profiler_object; struct nvgpu_runlist; @@ -102,6 +104,12 @@ struct nvgpu_tsg { */ struct nvgpu_list_node gr_ctx_mappings_list; + /** + * Pointer to multimedia engine context buffer for this TSG. Allocated during + * TSG open and freed during TSG release. + */ + struct nvgpu_multimedia_ctx *eng_ctx[NVGPU_MULTIMEDIA_ENGINE_MAX]; + /** * Mutex to prevent concurrent context initialization for channels * in same TSG. All channels in one TSG share the context buffer, @@ -110,6 +118,14 @@ struct nvgpu_tsg { */ struct nvgpu_mutex ctx_init_lock; + /** + * Mutex to prevent concurrent engine context initialization for the + * channels in the same TSG. All channels in a TSG share the same engine + * context buffer and only one of the channel needs to initialize the context. + * Rest of the channels will re-use it for a particular engine. + */ + struct nvgpu_mutex eng_ctx_lock; + /** * This ref is initialized during tsg setup s/w. * This is ref_get whenever a channel is bound to the TSG. diff --git a/drivers/gpu/nvgpu/os/linux/ioctl_channel.c b/drivers/gpu/nvgpu/os/linux/ioctl_channel.c index ca9304934..8b3f80755 100644 --- a/drivers/gpu/nvgpu/os/linux/ioctl_channel.c +++ b/drivers/gpu/nvgpu/os/linux/ioctl_channel.c @@ -500,7 +500,8 @@ static int __gk20a_channel_open(struct gk20a *g, struct nvgpu_cdev *cdev, if (runlist_id == -1) { tmp_runlist_id = nvgpu_grmgr_get_gpu_instance_runlist_id(g, gpu_instance_id); } else { - if (nvgpu_grmgr_is_valid_runlist_id(g, gpu_instance_id, runlist_id)) { + if (nvgpu_grmgr_is_valid_runlist_id(g, gpu_instance_id, runlist_id) || + nvgpu_engine_is_multimedia_runlist_id(g, runlist_id)) { tmp_runlist_id = runlist_id; } else { return -EINVAL; @@ -1266,9 +1267,17 @@ long gk20a_channel_ioctl(struct file *filp, } #endif - err = nvgpu_gr_exec_with_err_for_instance(g, gr_instance_id, - nvgpu_ioctl_channel_alloc_obj_ctx(ch, args->class_num, - args->flags)); + if (nvgpu_engine_is_multimedia_runlist_id(g, ch->runlist->id)) { + if (ch->g->ops.nvenc.multimedia_alloc_ctx != NULL) { + err = ch->g->ops.nvenc.multimedia_alloc_ctx(ch, args->class_num, 0); + } else { + err = -EINVAL; + } + } else { + err = nvgpu_gr_exec_with_err_for_instance(g, gr_instance_id, + nvgpu_ioctl_channel_alloc_obj_ctx(ch, args->class_num, + args->flags)); + } gk20a_idle(ch->g); break; } diff --git a/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c b/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c index 72bec2256..b2ac2906b 100644 --- a/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c +++ b/drivers/gpu/nvgpu/os/linux/ioctl_ctrl.c @@ -1195,6 +1195,8 @@ static void nvgpu_gpu_fetch_engine_info_item(struct gk20a *g, } else { dst_info->engine_id = NVGPU_GPU_ENGINE_ID_ASYNC_COPY; } + } else if (nvgpu_device_is_nvenc(g, dev)) { + dst_info->engine_id = NVGPU_GPU_ENGINE_ID_NVENC; } dst_info->engine_instance = dev_inst_id; @@ -1221,8 +1223,13 @@ static int nvgpu_gpu_get_engine_info( const struct nvgpu_device *dev = g->fifo.active_engines[i]; struct nvgpu_gpu_get_engine_info_item dst_info; - nvgpu_gpu_fetch_engine_info_item(g, &dst_info, dev, - dev->inst_id, gr_dev->runlist_id); + if (nvgpu_device_is_nvenc(g, dev)) { + nvgpu_gpu_fetch_engine_info_item(g, &dst_info, dev, + dev->inst_id, dev->runlist_id); + } else { + nvgpu_gpu_fetch_engine_info_item(g, &dst_info, dev, + dev->inst_id, gr_dev->runlist_id); + } if (report_index < max_buffer_engines) { err = copy_to_user(&dst_item_list[report_index], diff --git a/include/uapi/linux/nvgpu-ctrl.h b/include/uapi/linux/nvgpu-ctrl.h index bc149b558..4ac535382 100644 --- a/include/uapi/linux/nvgpu-ctrl.h +++ b/include/uapi/linux/nvgpu-ctrl.h @@ -672,6 +672,7 @@ struct nvgpu_gpu_get_engine_info_item { #define NVGPU_GPU_ENGINE_ID_GR 0 #define NVGPU_GPU_ENGINE_ID_GR_COPY 1 #define NVGPU_GPU_ENGINE_ID_ASYNC_COPY 2 +#define NVGPU_GPU_ENGINE_ID_NVENC 5 __u32 engine_id; __u32 engine_instance; diff --git a/libs/dgpu/libnvgpu-drv-dgpu_safe.export b/libs/dgpu/libnvgpu-drv-dgpu_safe.export index 759df8f69..766cd223b 100644 --- a/libs/dgpu/libnvgpu-drv-dgpu_safe.export +++ b/libs/dgpu/libnvgpu-drv-dgpu_safe.export @@ -1,4 +1,4 @@ -# Copyright (c) 2020-2022, NVIDIA CORPORATION. All rights reserved. +# Copyright (c) 2020-2023, NVIDIA CORPORATION. All rights reserved. bitmap_find_next_zero_area fb_gv11b_write_mmu_fault_buffer_get @@ -808,3 +808,7 @@ nvgpu_cic_rm_setup nvgpu_cic_rm_init_vars nvgpu_cic_rm_deinit_vars nvgpu_cic_rm_remove +nvgpu_nvenc_sw_init +nvgpu_nvenc_sw_deinit +nvgpu_nvenc_falcon_boot +nvgpu_nvenc_reset