int gk20a_as_dev_open(struct inode *inode, struct file *filp) { struct gk20a_as_share *as_share; struct gk20a *g; int err; gk20a_dbg_fn(""); g = container_of(inode->i_cdev, struct gk20a, as.cdev); err = gk20a_get_client(g); if (err) { gk20a_dbg_fn("fail to get channel!"); return err; } err = gk20a_as_alloc_share(&g->as, &as_share); if (err) { gk20a_dbg_fn("failed to alloc share"); gk20a_put_client(g); return err; } filp->private_data = as_share; return 0; }
static int gk20a_init_clk_setup_sw(struct gk20a *g) { struct clk_gk20a *clk = &g->clk; static int initialized; struct clk *ref; unsigned long ref_rate; gk20a_dbg_fn(""); if (clk->sw_ready) { gk20a_dbg_fn("skip init"); return 0; } if (!gk20a_clk_get(g)) return -EINVAL; ref = clk_get_parent(clk_get_parent(clk->tegra_clk)); if (IS_ERR(ref)) { gk20a_err(dev_from_gk20a(g), "failed to get GPCPLL reference clock"); return -EINVAL; } ref_rate = clk_get_rate(ref); clk->pll_delay = 300; /* usec */ clk->gpc_pll.id = GK20A_GPC_PLL; clk->gpc_pll.clk_in = ref_rate / KHZ; /* Decide initial frequency */ if (!initialized) { initialized = 1; clk->gpc_pll.M = 1; clk->gpc_pll.N = DIV_ROUND_UP(gpc_pll_params.min_vco, clk->gpc_pll.clk_in); clk->gpc_pll.PL = 1; clk->gpc_pll.freq = clk->gpc_pll.clk_in * clk->gpc_pll.N; clk->gpc_pll.freq /= pl_to_div[clk->gpc_pll.PL]; } mutex_init(&clk->clk_mutex); clk->sw_ready = true; gk20a_dbg_fn("done"); return 0; }
static int gk20a_as_alloc_share(struct gk20a_as *as, struct gk20a_as_share **out) { struct gk20a_as_share *as_share; int err = 0; gk20a_dbg_fn(""); *out = 0; as_share = kzalloc(sizeof(*as_share), GFP_KERNEL); if (!as_share) return -ENOMEM; as_share->as = as; as_share->id = generate_as_share_id(as_share->as); as_share->ref_cnt.counter = 1; /* this will set as_share->vm. */ err = gk20a_vm_alloc_share(as_share); if (err) goto failed; *out = as_share; return 0; failed: kfree(as_share); return err; }
/* Flushes the compression bit cache as well as "data". * Note: the name here is a bit of a misnomer. ELPG uses this * internally... but ELPG doesn't have to be on to do it manually. */ static void gk20a_mm_g_elpg_flush_locked(struct gk20a *g) { u32 data; s32 retry = 100; gk20a_dbg_fn(""); /* Make sure all previous writes are committed to the L2. There's no guarantee that writes are to DRAM. This will be a sysmembar internal to the L2. */ gk20a_writel(g, ltc_ltcs_ltss_g_elpg_r(), ltc_ltcs_ltss_g_elpg_flush_pending_f()); do { data = gk20a_readl(g, ltc_ltc0_ltss_g_elpg_r()); if (ltc_ltc0_ltss_g_elpg_flush_v(data) == ltc_ltc0_ltss_g_elpg_flush_pending_v()) { gk20a_dbg_info("g_elpg_flush 0x%x", data); retry--; usleep_range(20, 40); } else break; } while (retry >= 0 || !tegra_platform_is_silicon()); if (retry < 0) gk20a_warn(dev_from_gk20a(g), "g_elpg_flush too many retries"); }
static int vgpu_gr_alloc_channel_patch_ctx(struct gk20a *g, struct channel_gk20a *c) { struct gk20a_platform *platform = gk20a_get_platform(g->dev); struct patch_desc *patch_ctx = &c->ch_ctx.patch_ctx; struct vm_gk20a *ch_vm = c->vm; struct tegra_vgpu_cmd_msg msg; struct tegra_vgpu_gr_ctx_params *p = &msg.params.gr_ctx; int err; gk20a_dbg_fn(""); patch_ctx->mem.size = 128 * sizeof(u32); patch_ctx->mem.gpu_va = gk20a_vm_alloc_va(ch_vm, patch_ctx->mem.size, 0); if (!patch_ctx->mem.gpu_va) return -ENOMEM; msg.cmd = TEGRA_VGPU_CMD_CHANNEL_ALLOC_GR_PATCH_CTX; msg.handle = platform->virt_handle; p->handle = c->virt_ctx; p->patch_ctx_va = patch_ctx->mem.gpu_va; err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg)); if (err || msg.ret) { gk20a_vm_free_va(ch_vm, patch_ctx->mem.gpu_va, patch_ctx->mem.size, 0); err = -ENOMEM; } return err; }
static int gk20a_as_ioctl_free_space( struct gk20a_as_share *as_share, struct nvhost_as_free_space_args *args) { gk20a_dbg_fn(""); return gk20a_vm_free_space(as_share, args); }
static int gr_gm20b_handle_sw_method(struct gk20a *g, u32 addr, u32 class_num, u32 offset, u32 data) { gk20a_dbg_fn(""); if (class_num == MAXWELL_COMPUTE_B) { switch (offset << 2) { case NVB1C0_SET_SHADER_EXCEPTIONS: gk20a_gr_set_shader_exceptions(g, data); break; default: goto fail; } } if (class_num == MAXWELL_B) { switch (offset << 2) { case NVB197_SET_SHADER_EXCEPTIONS: gk20a_gr_set_shader_exceptions(g, data); break; case NVB197_SET_CIRCULAR_BUFFER_SIZE: g->ops.gr.set_circular_buffer_size(g, data); break; case NVB197_SET_ALPHA_CIRCULAR_BUFFER_SIZE: g->ops.gr.set_alpha_circular_buffer_size(g, data); break; default: goto fail; } } return 0; fail: return -EINVAL; }
static int vgpu_gr_add_zbc(struct gk20a *g, struct gr_gk20a *gr, struct zbc_entry *zbc_val) { struct gk20a_platform *platform = gk20a_get_platform(g->dev); struct tegra_vgpu_cmd_msg msg = {0}; struct tegra_vgpu_zbc_set_table_params *p = &msg.params.zbc_set_table; int err; gk20a_dbg_fn(""); msg.cmd = TEGRA_VGPU_CMD_ZBC_SET_TABLE; msg.handle = platform->virt_handle; p->type = zbc_val->type; p->format = zbc_val->format; switch (p->type) { case GK20A_ZBC_TYPE_COLOR: memcpy(p->color_ds, zbc_val->color_ds, sizeof(p->color_ds)); memcpy(p->color_l2, zbc_val->color_l2, sizeof(p->color_l2)); break; case GK20A_ZBC_TYPE_DEPTH: p->depth = zbc_val->depth; break; default: return -EINVAL; } err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg)); return (err || msg.ret) ? -ENOMEM : 0; }
static void vgpu_gr_detect_sm_arch(struct gk20a *g) { struct gk20a_platform *platform = gk20a_get_platform(g->dev); u32 v = 0, raw_version, version = 0; gk20a_dbg_fn(""); if (vgpu_get_attribute(platform->virt_handle, TEGRA_VGPU_ATTRIB_GPC0_TPC0_SM_ARCH, &v)) gk20a_err(dev_from_gk20a(g), "failed to retrieve SM arch"); raw_version = gr_gpc0_tpc0_sm_arch_spa_version_v(v); if (raw_version == gr_gpc0_tpc0_sm_arch_spa_version_smkepler_lp_v()) version = 0x320; /* SM 3.2 */ else gk20a_err(dev_from_gk20a(g), "Unknown SM version 0x%x", raw_version); /* on Kepler, SM version == SPA version */ g->gpu_characteristics.sm_arch_spa_version = version; g->gpu_characteristics.sm_arch_sm_version = version; g->gpu_characteristics.sm_arch_warp_count = gr_gpc0_tpc0_sm_arch_warp_count_v(v); }
static int vgpu_gr_alloc_global_ctx_buffers(struct gk20a *g) { struct gr_gk20a *gr = &g->gr; int attr_buffer_size; u32 cb_buffer_size = gr->bundle_cb_default_size * gr_scc_bundle_cb_size_div_256b_byte_granularity_v(); u32 pagepool_buffer_size = gr_scc_pagepool_total_pages_hwmax_value_v() * gr_scc_pagepool_total_pages_byte_granularity_v(); gk20a_dbg_fn(""); attr_buffer_size = g->ops.gr.calc_global_ctx_buffer_size(g); gk20a_dbg_info("cb_buffer_size : %d", cb_buffer_size); gr->global_ctx_buffer[CIRCULAR].mem.size = cb_buffer_size; gk20a_dbg_info("pagepool_buffer_size : %d", pagepool_buffer_size); gr->global_ctx_buffer[PAGEPOOL].mem.size = pagepool_buffer_size; gk20a_dbg_info("attr_buffer_size : %d", attr_buffer_size); gr->global_ctx_buffer[ATTRIBUTE].mem.size = attr_buffer_size; gk20a_dbg_info("priv access map size : %d", gr->ctx_vars.priv_access_map_size); gr->global_ctx_buffer[PRIV_ACCESS_MAP].mem.size = gr->ctx_vars.priv_access_map_size; return 0; }
static int vgpu_gr_get_zcull_info(struct gk20a *g, struct gr_gk20a *gr, struct gr_zcull_info *zcull_params) { struct gk20a_platform *platform = gk20a_get_platform(g->dev); struct tegra_vgpu_cmd_msg msg; struct tegra_vgpu_zcull_info_params *p = &msg.params.zcull_info; int err; gk20a_dbg_fn(""); msg.cmd = TEGRA_VGPU_CMD_GET_ZCULL_INFO; msg.handle = platform->virt_handle; err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg)); if (err || msg.ret) return -ENOMEM; zcull_params->width_align_pixels = p->width_align_pixels; zcull_params->height_align_pixels = p->height_align_pixels; zcull_params->pixel_squares_by_aliquots = p->pixel_squares_by_aliquots; zcull_params->aliquot_total = p->aliquot_total; zcull_params->region_byte_multiplier = p->region_byte_multiplier; zcull_params->region_header_size = p->region_header_size; zcull_params->subregion_header_size = p->subregion_header_size; zcull_params->subregion_width_align_pixels = p->subregion_width_align_pixels; zcull_params->subregion_height_align_pixels = p->subregion_height_align_pixels; zcull_params->subregion_count = p->subregion_count; return 0; }
static void vgpu_gr_free_channel_gr_ctx(struct channel_gk20a *c) { struct gk20a_platform *platform = gk20a_get_platform(c->g->dev); struct channel_ctx_gk20a *ch_ctx = &c->ch_ctx; struct vm_gk20a *ch_vm = c->vm; gk20a_dbg_fn(""); if (ch_ctx->gr_ctx && ch_ctx->gr_ctx->mem.gpu_va) { struct tegra_vgpu_cmd_msg msg; struct tegra_vgpu_gr_ctx_params *p = &msg.params.gr_ctx; int err; msg.cmd = TEGRA_VGPU_CMD_CHANNEL_FREE_GR_CTX; msg.handle = platform->virt_handle; p->handle = c->virt_ctx; err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg)); WARN_ON(err || msg.ret); gk20a_vm_free_va(ch_vm, ch_ctx->gr_ctx->mem.gpu_va, ch_ctx->gr_ctx->mem.size, 0); ch_ctx->gr_ctx->mem.gpu_va = 0; kfree(ch_ctx->gr_ctx); } }
static int gk20a_as_ioctl_unmap_buffer( struct gk20a_as_share *as_share, struct nvhost_as_unmap_buffer_args *args) { gk20a_dbg_fn(""); return gk20a_vm_unmap_buffer(as_share, args->offset); }
static void vgpu_gr_unmap_global_ctx_buffers(struct channel_gk20a *c) { struct gk20a_platform *platform = gk20a_get_platform(c->g->dev); struct vm_gk20a *ch_vm = c->vm; u64 *g_bfr_va = c->ch_ctx.global_ctx_buffer_va; u64 *g_bfr_size = c->ch_ctx.global_ctx_buffer_size; u32 i; gk20a_dbg_fn(""); if (c->ch_ctx.global_ctx_buffer_mapped) { struct tegra_vgpu_cmd_msg msg; struct tegra_vgpu_gr_ctx_params *p = &msg.params.gr_ctx; int err; msg.cmd = TEGRA_VGPU_CMD_CHANNEL_UNMAP_GR_GLOBAL_CTX; msg.handle = platform->virt_handle; p->handle = c->virt_ctx; err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg)); WARN_ON(err || msg.ret); } for (i = 0; i < NR_GLOBAL_CTX_BUF_VA; i++) { if (g_bfr_va[i]) { gk20a_vm_free_va(ch_vm, g_bfr_va[i], g_bfr_size[i], 0); g_bfr_va[i] = 0; g_bfr_size[i] = 0; } } c->ch_ctx.global_ctx_buffer_mapped = false; }
static void vgpu_remove_gr_support(struct gr_gk20a *gr) { gk20a_dbg_fn(""); gk20a_comptag_allocator_destroy(&gr->comp_tags); kfree(gr->gpc_tpc_mask); gr->gpc_tpc_mask = NULL; }
static int vgpu_gr_init_gr_setup_sw(struct gk20a *g) { struct gr_gk20a *gr = &g->gr; int err; gk20a_dbg_fn(""); if (gr->sw_ready) { gk20a_dbg_fn("skip init"); return 0; } gr->g = g; err = vgpu_gr_init_gr_config(g, gr); if (err) goto clean_up; err = vgpu_gr_init_ctx_state(g, gr); if (err) goto clean_up; err = g->ops.ltc.init_comptags(g, gr); if (err) goto clean_up; err = vgpu_gr_alloc_global_ctx_buffers(g); if (err) goto clean_up; mutex_init(&gr->ctx_mutex); gr->remove_support = vgpu_remove_gr_support; gr->sw_ready = true; gk20a_dbg_fn("done"); return 0; clean_up: gk20a_err(dev_from_gk20a(g), "fail"); vgpu_remove_gr_support(gr); return err; }
static int gk20a_as_ioctl_map_buffer( struct gk20a_as_share *as_share, struct nvhost_as_map_buffer_args *args) { gk20a_dbg_fn(""); return gk20a_vm_map_buffer(as_share, args->nvmap_handle, &args->o_a.align, args->flags, NV_KIND_DEFAULT); /* args->o_a.offset will be set if !err */ }
int vgpu_gr_isr(struct gk20a *g, struct tegra_vgpu_gr_intr_info *info) { struct fifo_gk20a *f = &g->fifo; struct channel_gk20a *ch = &f->channel[info->chid]; gk20a_dbg_fn(""); if (info->type != TEGRA_VGPU_GR_INTR_NOTIFY && info->type != TEGRA_VGPU_GR_INTR_SEMAPHORE) gk20a_err(dev_from_gk20a(g), "gr intr (%d) on ch %u", info->type, info->chid); switch (info->type) { case TEGRA_VGPU_GR_INTR_NOTIFY: wake_up(&ch->notifier_wq); break; case TEGRA_VGPU_GR_INTR_SEMAPHORE: gk20a_channel_event(ch); wake_up(&ch->semaphore_wq); break; case TEGRA_VGPU_GR_INTR_SEMAPHORE_TIMEOUT: gk20a_set_error_notifier(ch, NVGPU_CHANNEL_GR_SEMAPHORE_TIMEOUT); break; case TEGRA_VGPU_GR_INTR_ILLEGAL_NOTIFY: gk20a_set_error_notifier(ch, NVGPU_CHANNEL_GR_ILLEGAL_NOTIFY); case TEGRA_VGPU_GR_INTR_ILLEGAL_METHOD: break; case TEGRA_VGPU_GR_INTR_ILLEGAL_CLASS: gk20a_set_error_notifier(ch, NVGPU_CHANNEL_GR_ERROR_SW_NOTIFY); break; case TEGRA_VGPU_GR_INTR_FECS_ERROR: break; case TEGRA_VGPU_GR_INTR_CLASS_ERROR: gk20a_set_error_notifier(ch, NVGPU_CHANNEL_GR_ERROR_SW_NOTIFY); break; case TEGRA_VGPU_GR_INTR_FIRMWARE_METHOD: gk20a_set_error_notifier(ch, NVGPU_CHANNEL_GR_ERROR_SW_NOTIFY); break; case TEGRA_VGPU_GR_INTR_EXCEPTION: gk20a_set_error_notifier(ch, NVGPU_CHANNEL_GR_ERROR_SW_NOTIFY); break; default: WARN_ON(1); break; } return 0; }
static void gr_gm20b_set_circular_buffer_size(struct gk20a *g, u32 data) { struct gr_gk20a *gr = &g->gr; u32 gpc_index, ppc_index, stride, val; u32 cb_size = data * 4; gk20a_dbg_fn(""); if (cb_size > gr->attrib_cb_size) cb_size = gr->attrib_cb_size; gk20a_writel(g, gr_ds_tga_constraintlogic_r(), (gk20a_readl(g, gr_ds_tga_constraintlogic_r()) & ~gr_ds_tga_constraintlogic_beta_cbsize_f(~0)) | gr_ds_tga_constraintlogic_beta_cbsize_f(cb_size)); for (gpc_index = 0; gpc_index < gr->gpc_count; gpc_index++) { stride = proj_gpc_stride_v() * gpc_index; for (ppc_index = 0; ppc_index < gr->gpc_ppc_count[gpc_index]; ppc_index++) { val = gk20a_readl(g, gr_gpc0_ppc0_cbm_beta_cb_size_r() + stride + proj_ppc_in_gpc_stride_v() * ppc_index); val = set_field(val, gr_gpc0_ppc0_cbm_beta_cb_size_v_m(), gr_gpc0_ppc0_cbm_beta_cb_size_v_f(cb_size * gr->pes_tpc_count[ppc_index][gpc_index])); gk20a_writel(g, gr_gpc0_ppc0_cbm_beta_cb_size_r() + stride + proj_ppc_in_gpc_stride_v() * ppc_index, val); val = gk20a_readl(g, gr_gpcs_swdx_tc_beta_cb_size_r( ppc_index + gpc_index)); val = set_field(val, gr_gpcs_swdx_tc_beta_cb_size_v_m(), gr_gpcs_swdx_tc_beta_cb_size_v_f(cb_size * gr->gpc_ppc_count[gpc_index])); val = set_field(val, gr_gpcs_swdx_tc_beta_cb_size_div3_m(), gr_gpcs_swdx_tc_beta_cb_size_div3_f((cb_size * gr->gpc_ppc_count[gpc_index])/3)); gk20a_writel(g, gr_gpcs_swdx_tc_beta_cb_size_r( ppc_index + gpc_index), val); } } }
static u32 vgpu_gr_get_fbp_en_mask(struct gk20a *g) { struct gk20a_platform *platform = gk20a_get_platform(g->dev); u32 fbp_en_mask = 0; gk20a_dbg_fn(""); if (vgpu_get_attribute(platform->virt_handle, TEGRA_VGPU_ATTRIB_FBP_EN_MASK, &fbp_en_mask)) gk20a_err(dev_from_gk20a(g), "failed to retrieve fbp en mask"); return fbp_en_mask; }
static u32 vgpu_gr_get_max_fbps_count(struct gk20a *g) { struct gk20a_platform *platform = gk20a_get_platform(g->dev); u32 max_fbps_count = 0; gk20a_dbg_fn(""); if (vgpu_get_attribute(platform->virt_handle, TEGRA_VGPU_ATTRIB_NUM_FBPS, &max_fbps_count)) gk20a_err(dev_from_gk20a(g), "failed to retrieve num fbps"); return max_fbps_count; }
static int vgpu_determine_L2_size_bytes(struct gk20a *g) { struct gk20a_platform *platform = gk20a_get_platform(g->dev); u32 cache_size = 0; gk20a_dbg_fn(""); if (vgpu_get_attribute(platform->virt_handle, TEGRA_VGPU_ATTRIB_L2_SIZE, &cache_size)) dev_err(dev_from_gk20a(g), "unable to get L2 size"); return cache_size; }
int gk20a_ctrl_dev_open(struct inode *inode, struct file *filp) { struct gk20a *g; gk20a_dbg_fn(""); g = container_of(inode->i_cdev, struct gk20a, ctrl.cdev); filp->private_data = g->dev; return 0; }
int gk20a_as_dev_release(struct inode *inode, struct file *filp) { struct gk20a_as_share *as_share = filp->private_data; int ret; struct gk20a *g = gk20a_from_as(as_share->as); gk20a_dbg_fn(""); ret = gk20a_as_release_share(as_share); gk20a_put_client(g); return ret; }
/* * channels and the device nodes call this to release. * once the ref_cnt hits zero the share is deleted. */ int gk20a_as_release_share(struct gk20a_as_share *as_share) { int err; gk20a_dbg_fn(""); if (atomic_dec_return(&as_share->ref_cnt) > 0) return 0; err = gk20a_vm_release_share(as_share); release_as_share_id(as_share->as, as_share->id); kfree(as_share); return err; }
static int gk20a_init_clk_support(struct gk20a *g) { struct clk_gk20a *clk = &g->clk; u32 err; gk20a_dbg_fn(""); clk->g = g; err = gk20a_init_clk_reset_enable_hw(g); if (err) return err; err = gk20a_init_clk_setup_sw(g); if (err) return err; mutex_lock(&clk->clk_mutex); clk->clk_hw_on = true; err = gk20a_init_clk_setup_hw(g); mutex_unlock(&clk->clk_mutex); if (err) return err; err = gk20a_clk_register_export_ops(g); if (err) return err; /* FIXME: this effectively prevents host level clock gating */ err = clk_enable(g->clk.tegra_clk); if (err) return err; /* The prev call may not enable PLL if gbus is unbalanced - force it */ mutex_lock(&clk->clk_mutex); err = set_pll_freq(g, clk->gpc_pll.freq, clk->gpc_pll.freq); mutex_unlock(&clk->clk_mutex); if (err) return err; #ifdef CONFIG_DEBUG_FS if (!clk->debugfs_set) { if (!clk_gk20a_debugfs_init(g)) clk->debugfs_set = true; } #endif return err; }
static int vgpu_gr_alloc_channel_gr_ctx(struct gk20a *g, struct channel_gk20a *c) { struct gk20a_platform *platform = gk20a_get_platform(g->dev); struct tegra_vgpu_cmd_msg msg; struct tegra_vgpu_gr_ctx_params *p = &msg.params.gr_ctx; struct gr_gk20a *gr = &g->gr; struct gr_ctx_desc *gr_ctx; struct vm_gk20a *ch_vm = c->vm; int err; gk20a_dbg_fn(""); if (gr->ctx_vars.buffer_size == 0) return 0; /* alloc channel gr ctx buffer */ gr->ctx_vars.buffer_size = gr->ctx_vars.golden_image_size; gr->ctx_vars.buffer_total_size = gr->ctx_vars.golden_image_size; gr_ctx = kzalloc(sizeof(*gr_ctx), GFP_KERNEL); if (!gr_ctx) return -ENOMEM; gr_ctx->mem.size = gr->ctx_vars.buffer_total_size; gr_ctx->mem.gpu_va = gk20a_vm_alloc_va(ch_vm, gr_ctx->mem.size, 0); if (!gr_ctx->mem.gpu_va) { kfree(gr_ctx); return -ENOMEM; } msg.cmd = TEGRA_VGPU_CMD_CHANNEL_ALLOC_GR_CTX; msg.handle = platform->virt_handle; p->handle = c->virt_ctx; p->gr_ctx_va = gr_ctx->mem.gpu_va; p->class_num = c->obj_class; err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg)); if (err || msg.ret) { kfree(gr_ctx); gk20a_vm_free_va(ch_vm, gr_ctx->mem.gpu_va, gr_ctx->mem.size, 0); err = -ENOMEM; } else c->ch_ctx.gr_ctx = gr_ctx; return err; }
static int vgpu_gr_commit_inst(struct channel_gk20a *c, u64 gpu_va) { struct gk20a_platform *platform = gk20a_get_platform(c->g->dev); struct tegra_vgpu_cmd_msg msg; struct tegra_vgpu_gr_ctx_params *p = &msg.params.gr_ctx; int err; gk20a_dbg_fn(""); msg.cmd = TEGRA_VGPU_CMD_CHANNEL_COMMIT_GR_CTX; msg.handle = platform->virt_handle; p->handle = c->virt_ctx; err = vgpu_comm_sendrecv(&msg, sizeof(msg), sizeof(msg)); return (err || msg.ret) ? -1 : 0; }
static void vgpu_gr_free_channel_ctx(struct channel_gk20a *c) { gk20a_dbg_fn(""); vgpu_gr_unmap_global_ctx_buffers(c); vgpu_gr_free_channel_patch_ctx(c); if (!gk20a_is_channel_marked_as_tsg(c)) vgpu_gr_free_channel_gr_ctx(c); /* zcull_ctx, pm_ctx */ memset(&c->ch_ctx, 0, sizeof(struct channel_ctx_gk20a)); c->num_objects = 0; c->first_init = false; }
int vgpu_gr_nonstall_isr(struct gk20a *g, struct tegra_vgpu_gr_nonstall_intr_info *info) { gk20a_dbg_fn(""); switch (info->type) { case TEGRA_VGPU_GR_NONSTALL_INTR_SEMAPHORE: gk20a_channel_semaphore_wakeup(g); break; default: WARN_ON(1); break; } return 0; }