From 6393eddfa996fba03464f897b85aa5ec79860fed Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Mon, 29 Jan 2018 23:24:37 -0800 Subject: gpu: nvgpu: vgpu: move common files out of linux folder Most of files have been moved out of linux folder. More code could be common as halifying going on. Jira EVLR-2364 Change-Id: Ia9dbdbc82f45ceefe5c788eac7517000cd455d5e Signed-off-by: Richard Zhao Reviewed-on: https://git-master.nvidia.com/r/1649947 Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/gpu/nvgpu/vgpu/vgpu.c | 350 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 350 insertions(+) create mode 100644 drivers/gpu/nvgpu/vgpu/vgpu.c (limited to 'drivers/gpu/nvgpu/vgpu/vgpu.c') diff --git a/drivers/gpu/nvgpu/vgpu/vgpu.c b/drivers/gpu/nvgpu/vgpu/vgpu.c new file mode 100644 index 00000000..eb56d4f9 --- /dev/null +++ b/drivers/gpu/nvgpu/vgpu/vgpu.c @@ -0,0 +1,350 @@ +/* + * Copyright (c) 2014-2018, 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 "gk20a/gk20a.h" +#include "fecs_trace_vgpu.h" + +int vgpu_comm_init(struct gk20a *g) +{ + size_t queue_sizes[] = { TEGRA_VGPU_QUEUE_SIZES }; + + return vgpu_ivc_init(g, 3, queue_sizes, TEGRA_VGPU_QUEUE_CMD, + ARRAY_SIZE(queue_sizes)); +} + +void vgpu_comm_deinit(void) +{ + size_t queue_sizes[] = { TEGRA_VGPU_QUEUE_SIZES }; + + vgpu_ivc_deinit(TEGRA_VGPU_QUEUE_CMD, ARRAY_SIZE(queue_sizes)); +} + +int vgpu_comm_sendrecv(struct tegra_vgpu_cmd_msg *msg, size_t size_in, + size_t size_out) +{ + void *handle; + size_t size = size_in; + void *data = msg; + int err; + + err = vgpu_ivc_sendrecv(vgpu_ivc_get_server_vmid(), + TEGRA_VGPU_QUEUE_CMD, &handle, &data, &size); + if (!err) { + WARN_ON(size < size_out); + memcpy(msg, data, size_out); + vgpu_ivc_release(handle); + } + + return err; +} + +u64 vgpu_connect(void) +{ + struct tegra_vgpu_cmd_msg msg; + struct tegra_vgpu_connect_params *p = &msg.params.connect; + int err; + + msg.cmd = TEGRA_VGPU_CMD_CONNECT; + p->module = TEGRA_VGPU_MODULE_GPU; + err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg)); + + return (err || msg.ret) ? 0 : p->handle; +} + +int vgpu_get_attribute(u64 handle, u32 attrib, u32 *value) +{ + struct tegra_vgpu_cmd_msg msg; + struct tegra_vgpu_attrib_params *p = &msg.params.attrib; + int err; + + msg.cmd = TEGRA_VGPU_CMD_GET_ATTRIBUTE; + msg.handle = handle; + p->attrib = attrib; + err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg)); + + if (err || msg.ret) + return -1; + + *value = p->value; + return 0; +} + +static void vgpu_handle_channel_event(struct gk20a *g, + struct tegra_vgpu_channel_event_info *info) +{ + struct tsg_gk20a *tsg; + + if (!info->is_tsg) { + nvgpu_err(g, "channel event posted"); + return; + } + + if (info->id >= g->fifo.num_channels || + info->event_id >= TEGRA_VGPU_CHANNEL_EVENT_ID_MAX) { + nvgpu_err(g, "invalid channel event"); + return; + } + + tsg = &g->fifo.tsg[info->id]; + + gk20a_tsg_event_id_post_event(tsg, info->event_id); +} + +int vgpu_intr_thread(void *dev_id) +{ + struct gk20a *g = dev_id; + struct vgpu_priv_data *priv = vgpu_get_priv_data(g); + + while (true) { + struct tegra_vgpu_intr_msg *msg; + u32 sender; + void *handle; + size_t size; + int err; + + err = vgpu_ivc_recv(TEGRA_VGPU_QUEUE_INTR, &handle, + (void **)&msg, &size, &sender); + if (err == -ETIME) + continue; + if (WARN_ON(err)) + continue; + + if (msg->event == TEGRA_VGPU_EVENT_ABORT) { + vgpu_ivc_release(handle); + break; + } + + switch (msg->event) { + case TEGRA_VGPU_EVENT_INTR: + if (msg->unit == TEGRA_VGPU_INTR_GR) + vgpu_gr_isr(g, &msg->info.gr_intr); + else if (msg->unit == TEGRA_VGPU_NONSTALL_INTR_GR) + vgpu_gr_nonstall_isr(g, + &msg->info.gr_nonstall_intr); + else if (msg->unit == TEGRA_VGPU_INTR_FIFO) + vgpu_fifo_isr(g, &msg->info.fifo_intr); + else if (msg->unit == TEGRA_VGPU_NONSTALL_INTR_FIFO) + vgpu_fifo_nonstall_isr(g, + &msg->info.fifo_nonstall_intr); + else if (msg->unit == TEGRA_VGPU_NONSTALL_INTR_CE2) + vgpu_ce2_nonstall_isr(g, + &msg->info.ce2_nonstall_intr); + break; +#ifdef CONFIG_GK20A_CTXSW_TRACE + case TEGRA_VGPU_EVENT_FECS_TRACE: + vgpu_fecs_trace_data_update(g); + break; +#endif + case TEGRA_VGPU_EVENT_CHANNEL: + vgpu_handle_channel_event(g, &msg->info.channel_event); + break; + case TEGRA_VGPU_EVENT_SM_ESR: + vgpu_gr_handle_sm_esr_event(g, &msg->info.sm_esr); + break; + default: + nvgpu_err(g, "unknown event %u", msg->event); + break; + } + + vgpu_ivc_release(handle); + } + + while (!nvgpu_thread_should_stop(&priv->intr_handler)) + nvgpu_msleep(10); + return 0; +} + +void vgpu_remove_support_common(struct gk20a *g) +{ + struct vgpu_priv_data *priv = vgpu_get_priv_data(g); + struct tegra_vgpu_intr_msg msg; + int err; + + if (g->dbg_regops_tmp_buf) + nvgpu_kfree(g, g->dbg_regops_tmp_buf); + + if (g->pmu.remove_support) + g->pmu.remove_support(&g->pmu); + + if (g->gr.remove_support) + g->gr.remove_support(&g->gr); + + if (g->fifo.remove_support) + g->fifo.remove_support(&g->fifo); + + if (g->mm.remove_support) + g->mm.remove_support(&g->mm); + + msg.event = TEGRA_VGPU_EVENT_ABORT; + err = vgpu_ivc_send(vgpu_ivc_get_peer_self(), TEGRA_VGPU_QUEUE_INTR, + &msg, sizeof(msg)); + WARN_ON(err); + nvgpu_thread_stop(&priv->intr_handler); +} + +void vgpu_detect_chip(struct gk20a *g) +{ + struct nvgpu_gpu_params *p = &g->params; + struct vgpu_priv_data *priv = vgpu_get_priv_data(g); + + p->gpu_arch = priv->constants.arch; + p->gpu_impl = priv->constants.impl; + p->gpu_rev = priv->constants.rev; + + gk20a_dbg_info("arch: %x, impl: %x, rev: %x\n", + p->gpu_arch, + p->gpu_impl, + p->gpu_rev); +} + +int vgpu_init_gpu_characteristics(struct gk20a *g) +{ + int err; + + gk20a_dbg_fn(""); + + err = gk20a_init_gpu_characteristics(g); + if (err) + return err; + + __nvgpu_set_enabled(g, NVGPU_SUPPORT_MAP_BUFFER_BATCH, false); + + /* features vgpu does not support */ + __nvgpu_set_enabled(g, NVGPU_SUPPORT_RESCHEDULE_RUNLIST, false); + + return 0; +} + +int vgpu_read_ptimer(struct gk20a *g, u64 *value) +{ + struct tegra_vgpu_cmd_msg msg = {0}; + struct tegra_vgpu_read_ptimer_params *p = &msg.params.read_ptimer; + int err; + + gk20a_dbg_fn(""); + + msg.cmd = TEGRA_VGPU_CMD_READ_PTIMER; + msg.handle = vgpu_get_handle(g); + + err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg)); + err = err ? err : msg.ret; + if (!err) + *value = p->time; + else + nvgpu_err(g, "vgpu read ptimer failed, err=%d", err); + + return err; +} + +int vgpu_get_timestamps_zipper(struct gk20a *g, + u32 source_id, u32 count, + struct nvgpu_cpu_time_correlation_sample *samples) +{ + struct tegra_vgpu_cmd_msg msg = {0}; + struct tegra_vgpu_get_timestamps_zipper_params *p = + &msg.params.get_timestamps_zipper; + int err; + u32 i; + + gk20a_dbg_fn(""); + + if (count > TEGRA_VGPU_GET_TIMESTAMPS_ZIPPER_MAX_COUNT) { + nvgpu_err(g, "count %u overflow", count); + return -EINVAL; + } + + msg.cmd = TEGRA_VGPU_CMD_GET_TIMESTAMPS_ZIPPER; + msg.handle = vgpu_get_handle(g); + p->source_id = TEGRA_VGPU_GET_TIMESTAMPS_ZIPPER_SRC_ID_TSC; + p->count = count; + + err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg)); + err = err ? err : msg.ret; + if (err) { + nvgpu_err(g, "vgpu get timestamps zipper failed, err=%d", err); + return err; + } + + for (i = 0; i < count; i++) { + samples[i].cpu_timestamp = p->samples[i].cpu_timestamp; + samples[i].gpu_timestamp = p->samples[i].gpu_timestamp; + } + + return err; +} + +int vgpu_init_hal(struct gk20a *g) +{ + u32 ver = g->params.gpu_arch + g->params.gpu_impl; + int err; + + switch (ver) { + case NVGPU_GPUID_GP10B: + gk20a_dbg_info("gp10b detected"); + err = vgpu_gp10b_init_hal(g); + break; + case NVGPU_GPUID_GV11B: + err = vgpu_gv11b_init_hal(g); + break; + default: + nvgpu_err(g, "no support for %x", ver); + err = -ENODEV; + break; + } + + return err; +} + +int vgpu_get_constants(struct gk20a *g) +{ + struct tegra_vgpu_cmd_msg msg = {}; + struct tegra_vgpu_constants_params *p = &msg.params.constants; + struct vgpu_priv_data *priv = vgpu_get_priv_data(g); + int err; + + gk20a_dbg_fn(""); + + msg.cmd = TEGRA_VGPU_CMD_GET_CONSTANTS; + msg.handle = vgpu_get_handle(g); + err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg)); + err = err ? err : msg.ret; + + if (unlikely(err)) { + nvgpu_err(g, "%s failed, err=%d", __func__, err); + return err; + } + + if (unlikely(p->gpc_count > TEGRA_VGPU_MAX_GPC_COUNT || + p->max_tpc_per_gpc_count > TEGRA_VGPU_MAX_TPC_COUNT_PER_GPC)) { + nvgpu_err(g, "gpc_count %d max_tpc_per_gpc %d overflow", + (int)p->gpc_count, (int)p->max_tpc_per_gpc_count); + return -EINVAL; + } + + priv->constants = *p; + return 0; +} -- cgit v1.2.2