mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-24 02:22:34 +03:00
gpu: nvgpu: Add multiple engine and runlist support
This CL covers the following modification, 1) Added multiple engine_info support 2) Added multiple runlist_info support 3) Initial changes for ASYNC CE support 4) Added ASYNC CE interrupt handling support for gm206 GPU family 5) Added generic mechanism to identify the CE engine pri_base address for gm206 (CE0, CE1 and CE2) 6) Removed hard coded engine_id logic and made generic way 7) Code cleanup for readability JIRA DNVGPU-26 Change-Id: I2c3846c40bcc8d10c2dfb225caa4105fc9123b65 Signed-off-by: Lakshmanan M <lm@nvidia.com> Reviewed-on: http://git-master/r/1155963 Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com> Tested-by: Terje Bergstrom <tbergstrom@nvidia.com>
This commit is contained in:
committed by
Terje Bergstrom
parent
3d7263d3ca
commit
6299b00beb
@@ -80,7 +80,8 @@ nvgpu-y := \
|
||||
gm206/hal_gm206.o \
|
||||
gm206/gr_gm206.o \
|
||||
gm206/acr_gm206.o \
|
||||
gm206/pmu_gm206.o
|
||||
gm206/pmu_gm206.o \
|
||||
gm206/ce_gm206.o
|
||||
|
||||
nvgpu-$(CONFIG_TEGRA_GK20A) += gk20a/platform_gk20a_tegra.o
|
||||
nvgpu-$(CONFIG_SYNC) += gk20a/sync_gk20a.o
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* GK20A Graphics Copy Engine (gr host)
|
||||
*
|
||||
* Copyright (c) 2011-2015, NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (c) 2011-2016, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -57,7 +57,7 @@ static u32 ce2_launcherr_isr(struct gk20a *g, u32 fifo_intr)
|
||||
return ce2_intr_status_launcherr_pending_f();
|
||||
}
|
||||
|
||||
void gk20a_ce2_isr(struct gk20a *g)
|
||||
void gk20a_ce2_isr(struct gk20a *g, u32 inst_id, u32 pri_base)
|
||||
{
|
||||
u32 ce2_intr = gk20a_readl(g, ce2_intr_status_r());
|
||||
u32 clear_intr = 0;
|
||||
@@ -75,7 +75,7 @@ void gk20a_ce2_isr(struct gk20a *g)
|
||||
return;
|
||||
}
|
||||
|
||||
void gk20a_ce2_nonstall_isr(struct gk20a *g)
|
||||
void gk20a_ce2_nonstall_isr(struct gk20a *g, u32 inst_id, u32 pri_base)
|
||||
{
|
||||
u32 ce2_intr = gk20a_readl(g, ce2_intr_status_r());
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* GK20A graphics copy engine (gr host)
|
||||
*
|
||||
* Copyright (c) 2011-2015, NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (c) 2011-2016, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -25,7 +25,7 @@
|
||||
#include "tsg_gk20a.h"
|
||||
|
||||
void gk20a_init_ce2(struct gpu_ops *gops);
|
||||
void gk20a_ce2_isr(struct gk20a *g);
|
||||
void gk20a_ce2_nonstall_isr(struct gk20a *g);
|
||||
void gk20a_ce2_isr(struct gk20a *g, u32 inst_id, u32 pri_base);
|
||||
void gk20a_ce2_nonstall_isr(struct gk20a *g, u32 inst_id, u32 pri_base);
|
||||
|
||||
#endif /*__CE2_GK20A_H__*/
|
||||
|
||||
@@ -329,11 +329,17 @@ static void channel_gk20a_bind(struct channel_gk20a *c)
|
||||
{
|
||||
struct gk20a *g = c->g;
|
||||
struct fifo_gk20a *f = &g->fifo;
|
||||
struct fifo_engine_info_gk20a *engine_info =
|
||||
f->engine_info + ENGINE_GR_GK20A;
|
||||
u32 engine_id;
|
||||
struct fifo_engine_info_gk20a *engine_info = NULL;
|
||||
u32 inst_ptr = gk20a_mm_inst_block_addr(g, &c->inst_block)
|
||||
>> ram_in_base_shift_v();
|
||||
|
||||
/* TODO:Need to handle non GR engine channel bind path */
|
||||
engine_id = gk20a_fifo_get_gr_engine_id(g);
|
||||
|
||||
/* Consider 1st available GR engine */
|
||||
engine_info = (f->engine_info + engine_id);
|
||||
|
||||
gk20a_dbg_info("bind channel %d inst ptr 0x%08x",
|
||||
c->hw_chid, inst_ptr);
|
||||
|
||||
@@ -1716,7 +1722,7 @@ static void gk20a_channel_timeout_handler(struct work_struct *work)
|
||||
/* Get failing engine data */
|
||||
engine_id = gk20a_fifo_get_failing_engine_data(g, &id, &is_tsg);
|
||||
|
||||
if (engine_id >= g->fifo.max_engines) {
|
||||
if (!gk20a_fifo_is_valid_engine_id(g, engine_id)) {
|
||||
/* If no failing engine, abort the channels */
|
||||
if (gk20a_is_channel_marked_as_tsg(ch)) {
|
||||
struct tsg_gk20a *tsg = &g->fifo.tsg[ch->tsgid];
|
||||
|
||||
@@ -1102,11 +1102,10 @@ static int dbg_set_powergate(struct dbg_session_gk20a *dbg_s,
|
||||
false);
|
||||
g->ops.clock_gating.slcg_ltc_load_gating_prod(g,
|
||||
false);
|
||||
gr_gk20a_init_blcg_mode(g, BLCG_RUN, ENGINE_GR_GK20A);
|
||||
|
||||
gr_gk20a_init_cg_mode(g, BLCG_MODE, BLCG_RUN);
|
||||
g->elcg_enabled = false;
|
||||
gr_gk20a_init_elcg_mode(g, ELCG_RUN, ENGINE_GR_GK20A);
|
||||
gr_gk20a_init_elcg_mode(g, ELCG_RUN, ENGINE_CE2_GK20A);
|
||||
gr_gk20a_init_cg_mode(g, ELCG_MODE, ELCG_RUN);
|
||||
|
||||
}
|
||||
|
||||
@@ -1126,9 +1125,8 @@ static int dbg_set_powergate(struct dbg_session_gk20a *dbg_s,
|
||||
--g->dbg_powergating_disabled_refcount == 0) {
|
||||
|
||||
g->elcg_enabled = true;
|
||||
gr_gk20a_init_elcg_mode(g, ELCG_AUTO, ENGINE_CE2_GK20A);
|
||||
gr_gk20a_init_elcg_mode(g, ELCG_AUTO, ENGINE_GR_GK20A);
|
||||
gr_gk20a_init_blcg_mode(g, BLCG_AUTO, ENGINE_GR_GK20A);
|
||||
gr_gk20a_init_cg_mode(g, ELCG_MODE, ELCG_AUTO);
|
||||
gr_gk20a_init_cg_mode(g, BLCG_MODE, BLCG_AUTO);
|
||||
|
||||
g->ops.clock_gating.slcg_ltc_load_gating_prod(g,
|
||||
g->slcg_enabled);
|
||||
|
||||
@@ -40,6 +40,131 @@ static int gk20a_fifo_update_runlist_locked(struct gk20a *g, u32 runlist_id,
|
||||
u32 hw_chid, bool add,
|
||||
bool wait_for_finish);
|
||||
|
||||
u32 gk20a_fifo_get_engine_ids(struct gk20a *g,
|
||||
u32 engine_id[], u32 engine_id_sz,
|
||||
u32 engine_enum)
|
||||
{
|
||||
struct fifo_gk20a *f = NULL;
|
||||
u32 instance_cnt = 0;
|
||||
u32 engine_id_idx;
|
||||
u32 active_engine_id = 0;
|
||||
struct fifo_engine_info_gk20a *info = NULL;
|
||||
|
||||
if (g && engine_id_sz && (engine_enum < ENGINE_INVAL_GK20A)) {
|
||||
f = &g->fifo;
|
||||
for (engine_id_idx = 0; engine_id_idx < f->num_engines; ++engine_id_idx) {
|
||||
active_engine_id = f->active_engines_list[engine_id_idx];
|
||||
info = &f->engine_info[active_engine_id];
|
||||
|
||||
if (info->engine_enum == engine_enum) {
|
||||
if (instance_cnt < engine_id_sz) {
|
||||
engine_id[instance_cnt] = active_engine_id;
|
||||
++instance_cnt;
|
||||
} else {
|
||||
gk20a_dbg_info("warning engine_id table sz is small %d",
|
||||
engine_id_sz);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance_cnt;
|
||||
}
|
||||
|
||||
struct fifo_engine_info_gk20a *gk20a_fifo_get_engine_info(struct gk20a *g, u32 engine_id)
|
||||
{
|
||||
struct fifo_gk20a *f = NULL;
|
||||
u32 engine_id_idx;
|
||||
struct fifo_engine_info_gk20a *info = NULL;
|
||||
|
||||
if (!g)
|
||||
return info;
|
||||
|
||||
f = &g->fifo;
|
||||
|
||||
if (engine_id < f->max_engines) {
|
||||
for (engine_id_idx = 0; engine_id_idx < f->num_engines; ++engine_id_idx) {
|
||||
if (engine_id == f->active_engines_list[engine_id_idx]) {
|
||||
info = &f->engine_info[engine_id];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!info)
|
||||
gk20a_err(g->dev, "engine_id is not in active list/invalid %d", engine_id);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
bool gk20a_fifo_is_valid_engine_id(struct gk20a *g, u32 engine_id)
|
||||
{
|
||||
struct fifo_gk20a *f = NULL;
|
||||
u32 engine_id_idx;
|
||||
bool valid = false;
|
||||
|
||||
if (!g)
|
||||
return valid;
|
||||
|
||||
f = &g->fifo;
|
||||
|
||||
if (engine_id < f->max_engines) {
|
||||
for (engine_id_idx = 0; engine_id_idx < f->num_engines; ++engine_id_idx) {
|
||||
if (engine_id == f->active_engines_list[engine_id_idx]) {
|
||||
valid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!valid)
|
||||
gk20a_err(g->dev, "engine_id is not in active list/invalid %d", engine_id);
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
u32 gk20a_fifo_get_gr_engine_id(struct gk20a *g)
|
||||
{
|
||||
u32 gr_engine_cnt = 0;
|
||||
u32 gr_engine_id = FIFO_INVAL_ENGINE_ID;
|
||||
|
||||
/* Consider 1st available GR engine */
|
||||
gr_engine_cnt = gk20a_fifo_get_engine_ids(g, &gr_engine_id,
|
||||
1, ENGINE_GR_GK20A);
|
||||
|
||||
if (!gr_engine_cnt) {
|
||||
gk20a_err(dev_from_gk20a(g), "No GR engine available on this device!\n");
|
||||
}
|
||||
|
||||
return gr_engine_id;
|
||||
}
|
||||
|
||||
u32 gk20a_fifo_get_all_ce_engine_reset_mask(struct gk20a *g)
|
||||
{
|
||||
u32 reset_mask = 0;
|
||||
u32 engine_enum = ENGINE_INVAL_GK20A;
|
||||
struct fifo_gk20a *f = NULL;
|
||||
u32 engine_id_idx;
|
||||
struct fifo_engine_info_gk20a *engine_info;
|
||||
u32 active_engine_id = 0;
|
||||
|
||||
if (!g)
|
||||
return reset_mask;
|
||||
|
||||
f = &g->fifo;
|
||||
|
||||
for (engine_id_idx = 0; engine_id_idx < f->num_engines; ++engine_id_idx) {
|
||||
active_engine_id = f->active_engines_list[engine_id_idx];
|
||||
engine_info = &f->engine_info[active_engine_id];
|
||||
engine_enum = engine_info->engine_enum;
|
||||
|
||||
if ((engine_enum == ENGINE_GRCE_GK20A) ||
|
||||
(engine_enum == ENGINE_ASYNC_CE_GK20A))
|
||||
reset_mask |= engine_info->reset_mask;
|
||||
}
|
||||
|
||||
return reset_mask;
|
||||
}
|
||||
|
||||
/*
|
||||
* Link engine IDs to MMU IDs and vice versa.
|
||||
*/
|
||||
@@ -47,12 +172,14 @@ static int gk20a_fifo_update_runlist_locked(struct gk20a *g, u32 runlist_id,
|
||||
static inline u32 gk20a_engine_id_to_mmu_id(struct gk20a *g, u32 engine_id)
|
||||
{
|
||||
u32 fault_id = ~0;
|
||||
struct fifo_engine_info_gk20a *engine_info;
|
||||
|
||||
if (engine_id < ENGINE_INVAL_GK20A) {
|
||||
struct fifo_engine_info_gk20a *info =
|
||||
&g->fifo.engine_info[engine_id];
|
||||
engine_info = gk20a_fifo_get_engine_info(g, engine_id);
|
||||
|
||||
fault_id = info->fault_id;
|
||||
if (engine_info) {
|
||||
fault_id = engine_info->fault_id;
|
||||
} else {
|
||||
gk20a_err(g->dev, "engine_id is not in active list/invalid %d", engine_id);
|
||||
}
|
||||
return fault_id;
|
||||
}
|
||||
@@ -60,18 +187,19 @@ static inline u32 gk20a_engine_id_to_mmu_id(struct gk20a *g, u32 engine_id)
|
||||
static inline u32 gk20a_mmu_id_to_engine_id(struct gk20a *g, u32 fault_id)
|
||||
{
|
||||
u32 engine_id;
|
||||
u32 return_engine_id = ~0;
|
||||
u32 active_engine_id;
|
||||
struct fifo_engine_info_gk20a *engine_info;
|
||||
struct fifo_gk20a *f = &g->fifo;
|
||||
|
||||
for (engine_id = 0; engine_id < ENGINE_INVAL_GK20A; engine_id++) {
|
||||
struct fifo_engine_info_gk20a *info =
|
||||
&g->fifo.engine_info[engine_id];
|
||||
for (engine_id = 0; engine_id < f->num_engines; engine_id++) {
|
||||
active_engine_id = f->active_engines_list[engine_id];
|
||||
engine_info = &g->fifo.engine_info[active_engine_id];
|
||||
|
||||
if (info->fault_id == fault_id) {
|
||||
return_engine_id = engine_id;
|
||||
if (engine_info->fault_id == fault_id)
|
||||
break;
|
||||
}
|
||||
active_engine_id = FIFO_INVAL_ENGINE_ID;
|
||||
}
|
||||
return return_engine_id;
|
||||
return active_engine_id;
|
||||
}
|
||||
|
||||
int gk20a_fifo_engine_enum_from_type(struct gk20a *g, u32 engine_type,
|
||||
@@ -82,10 +210,15 @@ int gk20a_fifo_engine_enum_from_type(struct gk20a *g, u32 engine_type,
|
||||
gk20a_dbg_info("engine type %d", engine_type);
|
||||
if (engine_type == top_device_info_type_enum_graphics_v())
|
||||
ret = ENGINE_GR_GK20A;
|
||||
else if (engine_type == top_device_info_type_enum_copy2_v()) {
|
||||
ret = ENGINE_CE2_GK20A;
|
||||
else if ((engine_type >= top_device_info_type_enum_copy0_v()) &&
|
||||
(engine_type <= top_device_info_type_enum_copy2_v())) {
|
||||
/* Lets consider all the CE engine have separate runlist at this point
|
||||
* We can identify the ENGINE_GRCE_GK20A type CE using runlist_id
|
||||
* comparsion logic with GR runlist_id in init_engine_info() */
|
||||
ret = ENGINE_ASYNC_CE_GK20A;
|
||||
/* inst_id starts from CE0 to CE2 */
|
||||
if (inst_id)
|
||||
*inst_id = 0x2;
|
||||
*inst_id = (engine_type - top_device_info_type_enum_copy0_v());
|
||||
}
|
||||
else
|
||||
gk20a_err(g->dev, "unknown engine %d", engine_type);
|
||||
@@ -108,12 +241,11 @@ static int init_engine_info(struct fifo_gk20a *f)
|
||||
u32 inst_id = 0;
|
||||
u32 pri_base = 0;
|
||||
u32 fault_id = 0;
|
||||
u32 gr_runlist_id = ~0;
|
||||
|
||||
gk20a_dbg_fn("");
|
||||
|
||||
/* all we really care about finding is the graphics entry */
|
||||
/* especially early on in sim it probably thinks it has more */
|
||||
f->num_engines = 2;
|
||||
f->num_engines = 0;
|
||||
|
||||
for (i = 0; i < max_info_entries; i++) {
|
||||
u32 table_entry = gk20a_readl(f->g, top_device_info_r(i));
|
||||
@@ -168,8 +300,7 @@ static int init_engine_info(struct fifo_gk20a *f)
|
||||
g->ops.fifo.engine_enum_from_type(g,
|
||||
engine_type, &inst_id);
|
||||
} else if (entry == top_device_info_entry_data_v()) {
|
||||
/* gk20a don't support device_info_data
|
||||
packet parsing */
|
||||
/* gk20a doesn't support device_info_data packet parsing */
|
||||
if (g->ops.fifo.device_info_data_parse)
|
||||
g->ops.fifo.device_info_data_parse(g,
|
||||
table_entry, &inst_id, &pri_base,
|
||||
@@ -179,7 +310,7 @@ static int init_engine_info(struct fifo_gk20a *f)
|
||||
if (!top_device_info_chain_v(table_entry)) {
|
||||
if (engine_enum < ENGINE_INVAL_GK20A) {
|
||||
struct fifo_engine_info_gk20a *info =
|
||||
&g->fifo.engine_info[engine_enum];
|
||||
&g->fifo.engine_info[engine_id];
|
||||
|
||||
info->intr_mask |= BIT(intr_id);
|
||||
info->reset_mask |= BIT(reset_id);
|
||||
@@ -188,11 +319,25 @@ static int init_engine_info(struct fifo_gk20a *f)
|
||||
info->inst_id = inst_id;
|
||||
info->pri_base = pri_base;
|
||||
|
||||
if (!fault_id &&
|
||||
(engine_enum == ENGINE_CE2_GK20A))
|
||||
if (engine_enum == ENGINE_GR_GK20A)
|
||||
gr_runlist_id = runlist_id;
|
||||
|
||||
/* GR and GR_COPY shares same runlist_id */
|
||||
if ((engine_enum == ENGINE_ASYNC_CE_GK20A) &&
|
||||
(gr_runlist_id == runlist_id))
|
||||
engine_enum = ENGINE_GRCE_GK20A;
|
||||
|
||||
info->engine_enum = engine_enum;
|
||||
|
||||
if (!fault_id && (engine_enum == ENGINE_GRCE_GK20A))
|
||||
fault_id = 0x1b;
|
||||
info->fault_id = fault_id;
|
||||
|
||||
/* engine_id starts from 0 to NV_HOST_NUM_ENGINES */
|
||||
f->active_engines_list[f->num_engines] = engine_id;
|
||||
|
||||
++f->num_engines;
|
||||
|
||||
engine_enum = ENGINE_INVAL_GK20A;
|
||||
}
|
||||
}
|
||||
@@ -204,13 +349,19 @@ static int init_engine_info(struct fifo_gk20a *f)
|
||||
u32 gk20a_fifo_engine_interrupt_mask(struct gk20a *g)
|
||||
{
|
||||
u32 eng_intr_mask = 0;
|
||||
int i = 0;
|
||||
int i;
|
||||
u32 active_engine_id = 0;
|
||||
u32 engine_enum = ENGINE_INVAL_GK20A;
|
||||
|
||||
for (i = 0; i < g->fifo.max_engines; i++) {
|
||||
u32 intr_mask = g->fifo.engine_info[i].intr_mask;
|
||||
if (i == ENGINE_CE2_GK20A &&
|
||||
for (i = 0; i < g->fifo.num_engines; i++) {
|
||||
u32 intr_mask;
|
||||
active_engine_id = g->fifo.active_engines_list[i];
|
||||
intr_mask = g->fifo.engine_info[active_engine_id].intr_mask;
|
||||
engine_enum = g->fifo.engine_info[active_engine_id].engine_enum;
|
||||
if (((engine_enum == ENGINE_GRCE_GK20A) ||
|
||||
(engine_enum == ENGINE_ASYNC_CE_GK20A)) &&
|
||||
(!g->ops.ce2.isr_stall || !g->ops.ce2.isr_nonstall))
|
||||
continue;
|
||||
continue;
|
||||
|
||||
eng_intr_mask |= intr_mask;
|
||||
}
|
||||
@@ -218,13 +369,44 @@ u32 gk20a_fifo_engine_interrupt_mask(struct gk20a *g)
|
||||
return eng_intr_mask;
|
||||
}
|
||||
|
||||
void gk20a_fifo_delete_runlist(struct fifo_gk20a *f)
|
||||
{
|
||||
u32 i;
|
||||
u32 runlist_id;
|
||||
struct fifo_runlist_info_gk20a *runlist;
|
||||
struct gk20a *g = NULL;
|
||||
|
||||
if (!f || !f->runlist_info)
|
||||
return;
|
||||
|
||||
g = f->g;
|
||||
|
||||
for (runlist_id = 0; runlist_id < f->max_runlists; runlist_id++) {
|
||||
runlist = &f->runlist_info[runlist_id];
|
||||
for (i = 0; i < MAX_RUNLIST_BUFFERS; i++) {
|
||||
gk20a_gmmu_free(g, &runlist->mem[i]);
|
||||
}
|
||||
|
||||
kfree(runlist->active_channels);
|
||||
runlist->active_channels = NULL;
|
||||
|
||||
kfree(runlist->active_tsgs);
|
||||
runlist->active_tsgs = NULL;
|
||||
|
||||
mutex_destroy(&runlist->mutex);
|
||||
|
||||
}
|
||||
memset(f->runlist_info, 0, (sizeof(struct fifo_runlist_info_gk20a) *
|
||||
f->max_runlists));
|
||||
|
||||
kfree(f->runlist_info);
|
||||
f->runlist_info = NULL;
|
||||
f->max_runlists = 0;
|
||||
}
|
||||
|
||||
static void gk20a_remove_fifo_support(struct fifo_gk20a *f)
|
||||
{
|
||||
struct gk20a *g = f->g;
|
||||
struct fifo_engine_info_gk20a *engine_info;
|
||||
struct fifo_runlist_info_gk20a *runlist;
|
||||
u32 runlist_id;
|
||||
u32 i;
|
||||
|
||||
gk20a_dbg_fn("");
|
||||
|
||||
@@ -232,19 +414,14 @@ static void gk20a_remove_fifo_support(struct fifo_gk20a *f)
|
||||
vfree(f->tsg);
|
||||
gk20a_gmmu_unmap_free(&g->mm.bar1.vm, &f->userd);
|
||||
|
||||
engine_info = f->engine_info + ENGINE_GR_GK20A;
|
||||
runlist_id = engine_info->runlist_id;
|
||||
runlist = &f->runlist_info[runlist_id];
|
||||
gk20a_fifo_delete_runlist(f);
|
||||
|
||||
for (i = 0; i < MAX_RUNLIST_BUFFERS; i++)
|
||||
gk20a_gmmu_free(g, &runlist->mem[i]);
|
||||
|
||||
kfree(runlist->active_channels);
|
||||
kfree(runlist->active_tsgs);
|
||||
|
||||
kfree(f->runlist_info);
|
||||
kfree(f->pbdma_map);
|
||||
f->pbdma_map = NULL;
|
||||
kfree(f->engine_info);
|
||||
f->engine_info = NULL;
|
||||
kfree(f->active_engines_list);
|
||||
f->active_engines_list = NULL;
|
||||
}
|
||||
|
||||
/* reads info from hardware and fills in pbmda exception info record */
|
||||
@@ -327,69 +504,58 @@ static void fifo_engine_exception_status(struct gk20a *g,
|
||||
|
||||
static int init_runlist(struct gk20a *g, struct fifo_gk20a *f)
|
||||
{
|
||||
struct fifo_engine_info_gk20a *engine_info;
|
||||
struct fifo_runlist_info_gk20a *runlist;
|
||||
struct device *d = dev_from_gk20a(g);
|
||||
u32 runlist_id;
|
||||
s32 runlist_id = -1;
|
||||
u32 i;
|
||||
u64 runlist_size;
|
||||
|
||||
gk20a_dbg_fn("");
|
||||
|
||||
f->max_runlists = fifo_eng_runlist_base__size_1_v();
|
||||
f->max_runlists = g->ops.fifo.eng_runlist_base_size();
|
||||
f->runlist_info = kzalloc(sizeof(struct fifo_runlist_info_gk20a) *
|
||||
f->max_runlists, GFP_KERNEL);
|
||||
if (!f->runlist_info)
|
||||
goto clean_up;
|
||||
goto clean_up_runlist;
|
||||
|
||||
engine_info = f->engine_info + ENGINE_GR_GK20A;
|
||||
runlist_id = engine_info->runlist_id;
|
||||
runlist = &f->runlist_info[runlist_id];
|
||||
memset(f->runlist_info, 0, (sizeof(struct fifo_runlist_info_gk20a) *
|
||||
f->max_runlists));
|
||||
|
||||
runlist->active_channels =
|
||||
kzalloc(DIV_ROUND_UP(f->num_channels, BITS_PER_BYTE),
|
||||
GFP_KERNEL);
|
||||
if (!runlist->active_channels)
|
||||
goto clean_up_runlist_info;
|
||||
for (runlist_id = 0; runlist_id < f->max_runlists; runlist_id++) {
|
||||
runlist = &f->runlist_info[runlist_id];
|
||||
|
||||
runlist->active_tsgs =
|
||||
kzalloc(DIV_ROUND_UP(f->num_channels, BITS_PER_BYTE),
|
||||
GFP_KERNEL);
|
||||
if (!runlist->active_tsgs)
|
||||
goto clean_up_runlist_info;
|
||||
|
||||
runlist_size = ram_rl_entry_size_v() * f->num_runlist_entries;
|
||||
for (i = 0; i < MAX_RUNLIST_BUFFERS; i++) {
|
||||
int err = gk20a_gmmu_alloc(g, runlist_size, &runlist->mem[i]);
|
||||
if (err) {
|
||||
dev_err(d, "memory allocation failed\n");
|
||||
runlist->active_channels =
|
||||
kzalloc(DIV_ROUND_UP(f->num_channels, BITS_PER_BYTE),
|
||||
GFP_KERNEL);
|
||||
if (!runlist->active_channels)
|
||||
goto clean_up_runlist;
|
||||
}
|
||||
}
|
||||
mutex_init(&runlist->mutex);
|
||||
|
||||
/* None of buffers is pinned if this value doesn't change.
|
||||
Otherwise, one of them (cur_buffer) must have been pinned. */
|
||||
runlist->cur_buffer = MAX_RUNLIST_BUFFERS;
|
||||
runlist->active_tsgs =
|
||||
kzalloc(DIV_ROUND_UP(f->num_channels, BITS_PER_BYTE),
|
||||
GFP_KERNEL);
|
||||
if (!runlist->active_tsgs)
|
||||
goto clean_up_runlist;
|
||||
|
||||
runlist_size = ram_rl_entry_size_v() * f->num_runlist_entries;
|
||||
for (i = 0; i < MAX_RUNLIST_BUFFERS; i++) {
|
||||
int err = gk20a_gmmu_alloc(g, runlist_size, &runlist->mem[i]);
|
||||
if (err) {
|
||||
dev_err(d, "memory allocation failed\n");
|
||||
goto clean_up_runlist;
|
||||
}
|
||||
}
|
||||
mutex_init(&runlist->mutex);
|
||||
|
||||
/* None of buffers is pinned if this value doesn't change.
|
||||
Otherwise, one of them (cur_buffer) must have been pinned. */
|
||||
runlist->cur_buffer = MAX_RUNLIST_BUFFERS;
|
||||
}
|
||||
|
||||
gk20a_dbg_fn("done");
|
||||
return 0;
|
||||
|
||||
clean_up_runlist:
|
||||
for (i = 0; i < MAX_RUNLIST_BUFFERS; i++)
|
||||
gk20a_gmmu_free(g, &runlist->mem[i]);
|
||||
|
||||
clean_up_runlist_info:
|
||||
kfree(runlist->active_channels);
|
||||
runlist->active_channels = NULL;
|
||||
|
||||
kfree(runlist->active_tsgs);
|
||||
runlist->active_tsgs = NULL;
|
||||
|
||||
kfree(f->runlist_info);
|
||||
f->runlist_info = NULL;
|
||||
|
||||
clean_up:
|
||||
gk20a_fifo_delete_runlist(f);
|
||||
gk20a_dbg_fn("fail");
|
||||
return -ENOMEM;
|
||||
}
|
||||
@@ -543,7 +709,7 @@ static int gk20a_init_fifo_setup_sw(struct gk20a *g)
|
||||
f->num_channels = g->ops.fifo.get_num_fifos(g);
|
||||
f->num_runlist_entries = fifo_eng_runlist_length_max_v();
|
||||
f->num_pbdma = nvgpu_get_litter_value(g, GPU_LIT_HOST_NUM_PBDMA);
|
||||
f->max_engines = ENGINE_INVAL_GK20A;
|
||||
f->max_engines = nvgpu_get_litter_value(g, GPU_LIT_HOST_NUM_ENGINES);
|
||||
|
||||
f->userd_entry_size = 1 << ram_userd_base_shift_v();
|
||||
|
||||
@@ -563,11 +729,15 @@ static int gk20a_init_fifo_setup_sw(struct gk20a *g)
|
||||
GFP_KERNEL);
|
||||
f->engine_info = kzalloc(f->max_engines * sizeof(*f->engine_info),
|
||||
GFP_KERNEL);
|
||||
f->active_engines_list = kzalloc(f->max_engines * sizeof(u32),
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!(f->channel && f->pbdma_map && f->engine_info)) {
|
||||
if (!(f->channel && f->pbdma_map && f->engine_info &&
|
||||
f->active_engines_list)) {
|
||||
err = -ENOMEM;
|
||||
goto clean_up;
|
||||
}
|
||||
memset(f->active_engines_list, 0xff, (f->max_engines * sizeof(u32)));
|
||||
|
||||
/* pbdma map needs to be in place before calling engine info init */
|
||||
for (i = 0; i < f->num_pbdma; ++i)
|
||||
@@ -614,6 +784,8 @@ clean_up:
|
||||
f->pbdma_map = NULL;
|
||||
kfree(f->engine_info);
|
||||
f->engine_info = NULL;
|
||||
kfree(f->active_engines_list);
|
||||
f->active_engines_list = NULL;
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -829,9 +1001,29 @@ static inline void get_exception_mmu_fault_info(
|
||||
|
||||
void gk20a_fifo_reset_engine(struct gk20a *g, u32 engine_id)
|
||||
{
|
||||
struct fifo_gk20a *f = NULL;
|
||||
u32 engine_enum = ENGINE_INVAL_GK20A;
|
||||
u32 inst_id = 0;
|
||||
struct fifo_engine_info_gk20a *engine_info;
|
||||
|
||||
gk20a_dbg_fn("");
|
||||
|
||||
if (engine_id == ENGINE_GR_GK20A) {
|
||||
if (!g)
|
||||
return;
|
||||
|
||||
f = &g->fifo;
|
||||
|
||||
engine_info = gk20a_fifo_get_engine_info(g, engine_id);
|
||||
|
||||
if (engine_info) {
|
||||
engine_enum = engine_info->engine_enum;
|
||||
inst_id = engine_info->inst_id;
|
||||
}
|
||||
|
||||
if (engine_enum == ENGINE_INVAL_GK20A)
|
||||
gk20a_err(dev_from_gk20a(g), "unsupported engine_id %d", engine_id);
|
||||
|
||||
if (engine_enum == ENGINE_GR_GK20A) {
|
||||
if (support_gk20a_pmu(g->dev) && g->elpg_enabled)
|
||||
gk20a_pmu_disable_elpg(g);
|
||||
/* resetting engine will alter read/write index.
|
||||
@@ -848,8 +1040,10 @@ void gk20a_fifo_reset_engine(struct gk20a *g, u32 engine_id)
|
||||
if (support_gk20a_pmu(g->dev) && g->elpg_enabled)
|
||||
gk20a_pmu_enable_elpg(g);
|
||||
}
|
||||
if (engine_id == ENGINE_CE2_GK20A)
|
||||
gk20a_reset(g, mc_enable_ce2_m());
|
||||
if ((engine_enum == ENGINE_GRCE_GK20A) ||
|
||||
(engine_enum == ENGINE_ASYNC_CE_GK20A)) {
|
||||
gk20a_reset(g, engine_info->reset_mask);
|
||||
}
|
||||
}
|
||||
|
||||
static void gk20a_fifo_handle_chsw_fault(struct gk20a *g)
|
||||
@@ -872,6 +1066,24 @@ static void gk20a_fifo_handle_dropped_mmu_fault(struct gk20a *g)
|
||||
static bool gk20a_fifo_should_defer_engine_reset(struct gk20a *g, u32 engine_id,
|
||||
struct fifo_mmu_fault_info_gk20a *f, bool fake_fault)
|
||||
{
|
||||
u32 engine_enum = ENGINE_INVAL_GK20A;
|
||||
struct fifo_gk20a *fifo = NULL;
|
||||
struct fifo_engine_info_gk20a *engine_info;
|
||||
|
||||
if (!g || !f)
|
||||
return false;
|
||||
|
||||
fifo = &g->fifo;
|
||||
|
||||
engine_info = gk20a_fifo_get_engine_info(g, engine_id);
|
||||
|
||||
if (engine_info) {
|
||||
engine_enum = engine_info->engine_enum;
|
||||
}
|
||||
|
||||
if (engine_enum == ENGINE_INVAL_GK20A)
|
||||
return false;
|
||||
|
||||
/* channel recovery is only deferred if an sm debugger
|
||||
is attached and has MMU debug mode is enabled */
|
||||
if (!gk20a_gr_sm_debugger_attached(g) ||
|
||||
@@ -882,7 +1094,7 @@ static bool gk20a_fifo_should_defer_engine_reset(struct gk20a *g, u32 engine_id,
|
||||
if (fake_fault)
|
||||
return false;
|
||||
|
||||
if (engine_id != ENGINE_GR_GK20A ||
|
||||
if (engine_enum != ENGINE_GR_GK20A ||
|
||||
f->engine_subid_v != fifo_intr_mmu_fault_info_engine_subid_gpc_v())
|
||||
return false;
|
||||
|
||||
@@ -1001,8 +1213,8 @@ static bool gk20a_fifo_handle_mmu_fault(
|
||||
false);
|
||||
g->ops.clock_gating.slcg_ltc_load_gating_prod(g,
|
||||
false);
|
||||
gr_gk20a_init_elcg_mode(g, ELCG_RUN, ENGINE_GR_GK20A);
|
||||
gr_gk20a_init_elcg_mode(g, ELCG_RUN, ENGINE_CE2_GK20A);
|
||||
|
||||
gr_gk20a_init_cg_mode(g, ELCG_MODE, ELCG_RUN);
|
||||
|
||||
/* Disable fifo access */
|
||||
grfifo_ctl = gk20a_readl(g, gr_gpfifo_ctl_r());
|
||||
@@ -1219,7 +1431,7 @@ static void gk20a_fifo_trigger_mmu_fault(struct gk20a *g,
|
||||
|
||||
/* trigger faults for all bad engines */
|
||||
for_each_set_bit(engine_id, &engine_ids, 32) {
|
||||
if (engine_id > g->fifo.max_engines) {
|
||||
if (!gk20a_fifo_is_valid_engine_id(g, engine_id)) {
|
||||
WARN_ON(true);
|
||||
break;
|
||||
}
|
||||
@@ -1257,8 +1469,9 @@ static u32 gk20a_fifo_engines_on_id(struct gk20a *g, u32 id, bool is_tsg)
|
||||
int i;
|
||||
u32 engines = 0;
|
||||
|
||||
for (i = 0; i < g->fifo.max_engines; i++) {
|
||||
u32 status = gk20a_readl(g, fifo_engine_status_r(i));
|
||||
for (i = 0; i < g->fifo.num_engines; i++) {
|
||||
u32 active_engine_id = g->fifo.active_engines_list[i];
|
||||
u32 status = gk20a_readl(g, fifo_engine_status_r(active_engine_id));
|
||||
u32 ctx_status =
|
||||
fifo_engine_status_ctx_status_v(status);
|
||||
u32 ctx_id = (ctx_status ==
|
||||
@@ -1276,7 +1489,7 @@ static u32 gk20a_fifo_engines_on_id(struct gk20a *g, u32 id, bool is_tsg)
|
||||
fifo_engine_status_id_type_tsgid_v()) ||
|
||||
(!is_tsg && type ==
|
||||
fifo_engine_status_id_type_chid_v()))
|
||||
engines |= BIT(i);
|
||||
engines |= BIT(active_engine_id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1382,15 +1595,16 @@ void gk20a_fifo_recover(struct gk20a *g, u32 __engine_ids,
|
||||
ref_id_is_tsg = false;
|
||||
/* Reset *all* engines that use the
|
||||
* same channel as faulty engine */
|
||||
for (i = 0; i < g->fifo.max_engines; i++) {
|
||||
for (i = 0; i < g->fifo.num_engines; i++) {
|
||||
u32 active_engine_id = g->fifo.active_engines_list[i];
|
||||
u32 type;
|
||||
u32 id;
|
||||
|
||||
gk20a_fifo_get_faulty_id_type(g, i, &id, &type);
|
||||
gk20a_fifo_get_faulty_id_type(g, active_engine_id, &id, &type);
|
||||
if (ref_type == type && ref_id == id) {
|
||||
engine_ids |= BIT(i);
|
||||
engine_ids |= BIT(active_engine_id);
|
||||
mmu_fault_engines |=
|
||||
BIT(gk20a_engine_id_to_mmu_id(g, i));
|
||||
BIT(gk20a_engine_id_to_mmu_id(g, active_engine_id));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1453,16 +1667,21 @@ int gk20a_fifo_force_reset_ch(struct channel_gk20a *ch, bool verbose)
|
||||
u32 gk20a_fifo_get_failing_engine_data(struct gk20a *g,
|
||||
int *__id, bool *__is_tsg)
|
||||
{
|
||||
u32 engine_id = -1;
|
||||
u32 engine_id;
|
||||
int id = -1;
|
||||
bool is_tsg = false;
|
||||
u32 mailbox2;
|
||||
u32 active_engine_id = FIFO_INVAL_ENGINE_ID;
|
||||
|
||||
for (engine_id = 0; engine_id < g->fifo.max_engines; engine_id++) {
|
||||
u32 status = gk20a_readl(g, fifo_engine_status_r(engine_id));
|
||||
u32 ctx_status = fifo_engine_status_ctx_status_v(status);
|
||||
for (engine_id = 0; engine_id < g->fifo.num_engines; engine_id++) {
|
||||
u32 status;
|
||||
u32 ctx_status;
|
||||
bool failing_engine;
|
||||
|
||||
active_engine_id = g->fifo.active_engines_list[engine_id];
|
||||
status = gk20a_readl(g, fifo_engine_status_r(active_engine_id));
|
||||
ctx_status = fifo_engine_status_ctx_status_v(status);
|
||||
|
||||
/* we are interested in busy engines */
|
||||
failing_engine = fifo_engine_status_engine_v(status) ==
|
||||
fifo_engine_status_engine_busy_v();
|
||||
@@ -1476,8 +1695,10 @@ u32 gk20a_fifo_get_failing_engine_data(struct gk20a *g,
|
||||
|| ctx_status ==
|
||||
fifo_engine_status_ctx_status_ctxsw_load_v());
|
||||
|
||||
if (!failing_engine)
|
||||
if (!failing_engine) {
|
||||
active_engine_id = FIFO_INVAL_ENGINE_ID;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ctx_status ==
|
||||
fifo_engine_status_ctx_status_ctxsw_load_v()) {
|
||||
@@ -1500,7 +1721,7 @@ u32 gk20a_fifo_get_failing_engine_data(struct gk20a *g,
|
||||
*__id = id;
|
||||
*__is_tsg = is_tsg;
|
||||
|
||||
return engine_id;
|
||||
return active_engine_id;
|
||||
}
|
||||
|
||||
static bool gk20a_fifo_handle_sched_error(struct gk20a *g)
|
||||
@@ -1517,7 +1738,7 @@ static bool gk20a_fifo_handle_sched_error(struct gk20a *g)
|
||||
engine_id = gk20a_fifo_get_failing_engine_data(g, &id, &is_tsg);
|
||||
|
||||
/* could not find the engine - should never happen */
|
||||
if (unlikely(engine_id >= g->fifo.max_engines)) {
|
||||
if (!gk20a_fifo_is_valid_engine_id(g, engine_id)) {
|
||||
gk20a_err(dev_from_gk20a(g), "fifo sched error : 0x%08x, failed to find engine\n",
|
||||
sched_error);
|
||||
ret = false;
|
||||
@@ -1627,14 +1848,16 @@ static u32 fifo_error_isr(struct gk20a *g, u32 fifo_intr)
|
||||
"channel reset initiated from %s; intr=0x%08x",
|
||||
__func__, fifo_intr);
|
||||
for (engine_id = 0;
|
||||
engine_id < g->fifo.max_engines;
|
||||
engine_id < g->fifo.num_engines;
|
||||
engine_id++) {
|
||||
gk20a_dbg_fn("enum:%d -> engine_id:%d", engine_id,
|
||||
g->fifo.engine_info[engine_id].engine_id);
|
||||
fifo_pbdma_exception_status(g,
|
||||
&g->fifo.engine_info[engine_id]);
|
||||
fifo_engine_exception_status(g,
|
||||
&g->fifo.engine_info[engine_id]);
|
||||
u32 active_engine_id = g->fifo.active_engines_list[engine_id];
|
||||
u32 engine_enum = g->fifo.engine_info[active_engine_id].engine_enum;
|
||||
gk20a_dbg_fn("enum:%d -> engine_id:%d", engine_enum,
|
||||
active_engine_id);
|
||||
fifo_pbdma_exception_status(g,
|
||||
&g->fifo.engine_info[active_engine_id]);
|
||||
fifo_engine_exception_status(g,
|
||||
&g->fifo.engine_info[active_engine_id]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2057,12 +2280,13 @@ int gk20a_fifo_enable_all_engine_activity(struct gk20a *g)
|
||||
int i;
|
||||
int err = 0, ret = 0;
|
||||
|
||||
for (i = 0; i < g->fifo.max_engines; i++) {
|
||||
for (i = 0; i < g->fifo.num_engines; i++) {
|
||||
u32 active_engine_id = g->fifo.active_engines_list[i];
|
||||
err = gk20a_fifo_enable_engine_activity(g,
|
||||
&g->fifo.engine_info[i]);
|
||||
&g->fifo.engine_info[active_engine_id]);
|
||||
if (err) {
|
||||
gk20a_err(dev_from_gk20a(g),
|
||||
"failed to enable engine %d activity\n", i);
|
||||
"failed to enable engine %d activity\n", active_engine_id);
|
||||
ret = err;
|
||||
}
|
||||
}
|
||||
@@ -2149,14 +2373,16 @@ int gk20a_fifo_disable_all_engine_activity(struct gk20a *g,
|
||||
{
|
||||
int i;
|
||||
int err = 0, ret = 0;
|
||||
u32 active_engine_id;
|
||||
|
||||
for (i = 0; i < g->fifo.max_engines; i++) {
|
||||
for (i = 0; i < g->fifo.num_engines; i++) {
|
||||
active_engine_id = g->fifo.active_engines_list[i];
|
||||
err = gk20a_fifo_disable_engine_activity(g,
|
||||
&g->fifo.engine_info[i],
|
||||
&g->fifo.engine_info[active_engine_id],
|
||||
wait_for_idle);
|
||||
if (err) {
|
||||
gk20a_err(dev_from_gk20a(g),
|
||||
"failed to disable engine %d activity\n", i);
|
||||
"failed to disable engine %d activity\n", active_engine_id);
|
||||
ret = err;
|
||||
break;
|
||||
}
|
||||
@@ -2164,11 +2390,12 @@ int gk20a_fifo_disable_all_engine_activity(struct gk20a *g,
|
||||
|
||||
if (err) {
|
||||
while (--i >= 0) {
|
||||
active_engine_id = g->fifo.active_engines_list[i];
|
||||
err = gk20a_fifo_enable_engine_activity(g,
|
||||
&g->fifo.engine_info[i]);
|
||||
&g->fifo.engine_info[active_engine_id]);
|
||||
if (err)
|
||||
gk20a_err(dev_from_gk20a(g),
|
||||
"failed to re-enable engine %d activity\n", i);
|
||||
"failed to re-enable engine %d activity\n", active_engine_id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2181,14 +2408,15 @@ static void gk20a_fifo_runlist_reset_engines(struct gk20a *g, u32 runlist_id)
|
||||
u32 engines = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < f->max_engines; i++) {
|
||||
u32 status = gk20a_readl(g, fifo_engine_status_r(i));
|
||||
for (i = 0; i < f->num_engines; i++) {
|
||||
u32 active_engine_id = g->fifo.active_engines_list[i];
|
||||
u32 status = gk20a_readl(g, fifo_engine_status_r(active_engine_id));
|
||||
bool engine_busy = fifo_engine_status_engine_v(status) ==
|
||||
fifo_engine_status_engine_busy_v();
|
||||
|
||||
if (engine_busy &&
|
||||
(f->engine_info[i].runlist_id == runlist_id))
|
||||
engines |= BIT(i);
|
||||
(f->engine_info[active_engine_id].runlist_id == runlist_id))
|
||||
engines |= BIT(active_engine_id);
|
||||
}
|
||||
|
||||
if (engines)
|
||||
@@ -2669,8 +2897,10 @@ static int gk20a_fifo_sched_debugfs_seq_show(
|
||||
struct fifo_runlist_info_gk20a *runlist;
|
||||
u32 runlist_id;
|
||||
int ret = SEQ_SKIP;
|
||||
u32 engine_id;
|
||||
|
||||
engine_info = f->engine_info + ENGINE_GR_GK20A;
|
||||
engine_id = gk20a_fifo_get_gr_engine_id(g);
|
||||
engine_info = (f->engine_info + engine_id);
|
||||
runlist_id = engine_info->runlist_id;
|
||||
runlist = &f->runlist_info[runlist_id];
|
||||
|
||||
@@ -2772,6 +3002,7 @@ void gk20a_init_fifo(struct gpu_ops *gops)
|
||||
gops->fifo.set_runlist_interleave = gk20a_fifo_set_runlist_interleave;
|
||||
gops->fifo.force_reset_ch = gk20a_fifo_force_reset_ch;
|
||||
gops->fifo.engine_enum_from_type = gk20a_fifo_engine_enum_from_type;
|
||||
/* gk20a don't support device_info_data packet parsing */
|
||||
/* gk20a doesn't support device_info_data packet parsing */
|
||||
gops->fifo.device_info_data_parse = NULL;
|
||||
gops->fifo.eng_runlist_base_size = fifo_eng_runlist_base__size_1_v;
|
||||
}
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
|
||||
#define MAX_RUNLIST_BUFFERS 2
|
||||
|
||||
#define FIFO_INVAL_ENGINE_ID ~0
|
||||
|
||||
/* generally corresponds to the "pbdma" engine */
|
||||
|
||||
struct fifo_runlist_info_gk20a {
|
||||
@@ -40,10 +42,10 @@ struct fifo_runlist_info_gk20a {
|
||||
struct mutex mutex; /* protect channel preempt and runlist upate */
|
||||
};
|
||||
|
||||
/* so far gk20a has two engines: gr and ce2(gr_copy) */
|
||||
enum {
|
||||
ENGINE_GR_GK20A = 0,
|
||||
ENGINE_CE2_GK20A = 1,
|
||||
ENGINE_GRCE_GK20A = 1,
|
||||
ENGINE_ASYNC_CE_GK20A = 2,
|
||||
ENGINE_INVAL_GK20A
|
||||
};
|
||||
|
||||
@@ -85,6 +87,7 @@ struct fifo_engine_info_gk20a {
|
||||
u32 inst_id;
|
||||
u32 pri_base;
|
||||
u32 fault_id;
|
||||
u32 engine_enum;
|
||||
struct fifo_pbdma_exception_info_gk20a pbdma_exception_info;
|
||||
struct fifo_engine_exception_info_gk20a engine_exception_info;
|
||||
struct fifo_mmu_fault_info_gk20a mmu_fault_info;
|
||||
@@ -102,6 +105,7 @@ struct fifo_gk20a {
|
||||
struct fifo_engine_info_gk20a *engine_info;
|
||||
u32 max_engines;
|
||||
u32 num_engines;
|
||||
u32 *active_engines_list;
|
||||
|
||||
struct fifo_runlist_info_gk20a *runlist_info;
|
||||
u32 max_runlists;
|
||||
@@ -228,4 +232,15 @@ const char *gk20a_fifo_interleave_level_name(u32 interleave_level);
|
||||
int gk20a_fifo_engine_enum_from_type(struct gk20a *g, u32 engine_type,
|
||||
u32 *inst_id);
|
||||
|
||||
u32 gk20a_fifo_get_engine_ids(struct gk20a *g, u32 engine_id[], u32 engine_id_sz, u32 engine_enum);
|
||||
|
||||
void gk20a_fifo_delete_runlist(struct fifo_gk20a *f);
|
||||
|
||||
struct fifo_engine_info_gk20a *gk20a_fifo_get_engine_info(struct gk20a *g, u32 engine_id);
|
||||
|
||||
bool gk20a_fifo_is_valid_engine_id(struct gk20a *g, u32 engine_id);
|
||||
|
||||
u32 gk20a_fifo_get_gr_engine_id(struct gk20a *g);
|
||||
|
||||
u32 gk20a_fifo_get_all_ce_engine_reset_mask(struct gk20a *g);
|
||||
#endif /*__GR_GK20A_H__*/
|
||||
|
||||
@@ -1890,7 +1890,7 @@ void gk20a_enable(struct gk20a *g, u32 units)
|
||||
void gk20a_reset(struct gk20a *g, u32 units)
|
||||
{
|
||||
gk20a_disable(g, units);
|
||||
if (units & mc_enable_ce2_enabled_f())
|
||||
if (units & gk20a_fifo_get_all_ce_engine_reset_mask(g))
|
||||
udelay(500);
|
||||
else
|
||||
udelay(20);
|
||||
|
||||
@@ -90,6 +90,7 @@ enum nvgpu_litter_value {
|
||||
GPU_LIT_ROP_BASE,
|
||||
GPU_LIT_ROP_STRIDE,
|
||||
GPU_LIT_ROP_SHARED_BASE,
|
||||
GPU_LIT_HOST_NUM_ENGINES,
|
||||
GPU_LIT_HOST_NUM_PBDMA,
|
||||
GPU_LIT_LTC_STRIDE,
|
||||
GPU_LIT_LTS_STRIDE,
|
||||
@@ -120,8 +121,8 @@ struct gpu_ops {
|
||||
void (*flush)(struct gk20a *g);
|
||||
} ltc;
|
||||
struct {
|
||||
void (*isr_stall)(struct gk20a *g);
|
||||
void (*isr_nonstall)(struct gk20a *g);
|
||||
void (*isr_stall)(struct gk20a *g, u32 inst_id, u32 pri_base);
|
||||
void (*isr_nonstall)(struct gk20a *g, u32 inst_id, u32 pri_base);
|
||||
} ce2;
|
||||
struct {
|
||||
int (*init_fs_state)(struct gk20a *g);
|
||||
@@ -350,6 +351,7 @@ struct gpu_ops {
|
||||
int (*tsg_bind_channel)(struct tsg_gk20a *tsg,
|
||||
struct channel_gk20a *ch);
|
||||
int (*tsg_unbind_channel)(struct channel_gk20a *ch);
|
||||
u32 (*eng_runlist_base_size)(void);
|
||||
} fifo;
|
||||
struct pmu_v {
|
||||
/*used for change of enum zbc update cmd id from ver 0 to ver1*/
|
||||
|
||||
@@ -50,13 +50,12 @@ static ssize_t elcg_enable_store(struct device *dev,
|
||||
|
||||
if (val) {
|
||||
g->elcg_enabled = true;
|
||||
gr_gk20a_init_elcg_mode(g, ELCG_AUTO, ENGINE_GR_GK20A);
|
||||
gr_gk20a_init_elcg_mode(g, ELCG_AUTO, ENGINE_CE2_GK20A);
|
||||
gr_gk20a_init_cg_mode(g, ELCG_MODE, ELCG_AUTO);
|
||||
} else {
|
||||
g->elcg_enabled = false;
|
||||
gr_gk20a_init_elcg_mode(g, ELCG_RUN, ENGINE_GR_GK20A);
|
||||
gr_gk20a_init_elcg_mode(g, ELCG_RUN, ENGINE_CE2_GK20A);
|
||||
gr_gk20a_init_cg_mode(g, ELCG_MODE, ELCG_RUN);
|
||||
}
|
||||
|
||||
gk20a_idle(g->dev);
|
||||
|
||||
dev_info(dev, "ELCG is %s.\n", g->elcg_enabled ? "enabled" :
|
||||
|
||||
@@ -326,9 +326,12 @@ int gr_gk20a_wait_idle(struct gk20a *g, unsigned long end_jiffies,
|
||||
bool gr_enabled;
|
||||
bool ctxsw_active;
|
||||
bool gr_busy;
|
||||
u32 gr_engine_id;
|
||||
|
||||
gk20a_dbg_fn("");
|
||||
|
||||
gr_engine_id = gk20a_fifo_get_gr_engine_id(g);
|
||||
|
||||
do {
|
||||
/* fmodel: host gets fifo_engine_status(gr) from gr
|
||||
only when gr_status is read */
|
||||
@@ -338,7 +341,7 @@ int gr_gk20a_wait_idle(struct gk20a *g, unsigned long end_jiffies,
|
||||
mc_enable_pgraph_enabled_f();
|
||||
|
||||
ctxsw_active = gk20a_readl(g,
|
||||
fifo_engine_status_r(ENGINE_GR_GK20A)) &
|
||||
fifo_engine_status_r(gr_engine_id)) &
|
||||
fifo_engine_status_ctxsw_in_progress_f();
|
||||
|
||||
gr_busy = gk20a_readl(g, gr_engine_status_r()) &
|
||||
@@ -3905,11 +3908,14 @@ int gr_gk20a_add_zbc_depth(struct gk20a *g, struct gr_gk20a *gr,
|
||||
void gr_gk20a_pmu_save_zbc(struct gk20a *g, u32 entries)
|
||||
{
|
||||
struct fifo_gk20a *f = &g->fifo;
|
||||
struct fifo_engine_info_gk20a *gr_info =
|
||||
f->engine_info + ENGINE_GR_GK20A;
|
||||
struct fifo_engine_info_gk20a *gr_info = NULL;
|
||||
unsigned long end_jiffies = jiffies +
|
||||
msecs_to_jiffies(gk20a_get_gr_idle_timeout(g));
|
||||
u32 ret;
|
||||
u32 engine_id;
|
||||
|
||||
engine_id = gk20a_fifo_get_gr_engine_id(g);
|
||||
gr_info = (f->engine_info + engine_id);
|
||||
|
||||
ret = gk20a_fifo_disable_engine_activity(g, gr_info, true);
|
||||
if (ret) {
|
||||
@@ -4187,9 +4193,13 @@ int _gk20a_gr_zbc_set_table(struct gk20a *g, struct gr_gk20a *gr,
|
||||
struct zbc_entry *zbc_val)
|
||||
{
|
||||
struct fifo_gk20a *f = &g->fifo;
|
||||
struct fifo_engine_info_gk20a *gr_info = f->engine_info + ENGINE_GR_GK20A;
|
||||
struct fifo_engine_info_gk20a *gr_info = NULL;
|
||||
unsigned long end_jiffies;
|
||||
int ret;
|
||||
u32 engine_id;
|
||||
|
||||
engine_id = gk20a_fifo_get_gr_engine_id(g);
|
||||
gr_info = (f->engine_info + engine_id);
|
||||
|
||||
ret = gk20a_fifo_disable_engine_activity(g, gr_info, true);
|
||||
if (ret) {
|
||||
@@ -4308,6 +4318,29 @@ void gr_gk20a_init_elcg_mode(struct gk20a *g, u32 mode, u32 engine)
|
||||
gk20a_writel(g, therm_hubmmu_idle_filter_r(), idle_filter);
|
||||
}
|
||||
|
||||
void gr_gk20a_init_cg_mode(struct gk20a *g, u32 cgmode, u32 mode_config)
|
||||
{
|
||||
u32 engine_idx;
|
||||
u32 active_engine_id = 0;
|
||||
struct fifo_engine_info_gk20a *engine_info = NULL;
|
||||
struct fifo_gk20a *f = &g->fifo;
|
||||
|
||||
for (engine_idx = 0; engine_idx < f->num_engines; ++engine_idx) {
|
||||
active_engine_id = f->active_engines_list[engine_idx];
|
||||
engine_info = &f->engine_info[active_engine_id];
|
||||
|
||||
/* gr_engine supports both BLCG and ELCG */
|
||||
if ((cgmode == BLCG_MODE) &&
|
||||
(engine_info->engine_enum == ENGINE_GR_GK20A)) {
|
||||
gr_gk20a_init_blcg_mode(g, mode_config, active_engine_id);
|
||||
break;
|
||||
} else if (cgmode == ELCG_MODE)
|
||||
gr_gk20a_init_elcg_mode(g, mode_config, active_engine_id);
|
||||
else
|
||||
gk20a_err(dev_from_gk20a(g), "invalid cg mode %d %d", cgmode, mode_config);
|
||||
}
|
||||
}
|
||||
|
||||
static int gr_gk20a_zcull_init_hw(struct gk20a *g, struct gr_gk20a *gr)
|
||||
{
|
||||
u32 gpc_index, gpc_tpc_count, gpc_zcull_count;
|
||||
@@ -4710,8 +4743,9 @@ static int gk20a_init_gr_prepare(struct gk20a *g)
|
||||
{
|
||||
u32 gpfifo_ctrl, pmc_en;
|
||||
u32 err = 0;
|
||||
struct fifo_engine_info_gk20a *ce_info =
|
||||
g->fifo.engine_info + ENGINE_CE2_GK20A;
|
||||
u32 ce_reset_mask;
|
||||
|
||||
ce_reset_mask = gk20a_fifo_get_all_ce_engine_reset_mask(g);
|
||||
|
||||
/* disable fifo access */
|
||||
pmc_en = gk20a_readl(g, mc_enable_r());
|
||||
@@ -4725,12 +4759,12 @@ static int gk20a_init_gr_prepare(struct gk20a *g)
|
||||
gk20a_reset(g, mc_enable_pgraph_enabled_f()
|
||||
| mc_enable_blg_enabled_f()
|
||||
| mc_enable_perfmon_enabled_f()
|
||||
| ce_info->reset_mask);
|
||||
| ce_reset_mask);
|
||||
|
||||
gr_gk20a_load_gating_prod(g);
|
||||
|
||||
/* Disable elcg until it gets enabled later in the init*/
|
||||
gr_gk20a_init_elcg_mode(g, ELCG_RUN, ENGINE_GR_GK20A);
|
||||
gr_gk20a_init_elcg_mode(g, ELCG_RUN, ENGINE_CE2_GK20A);
|
||||
gr_gk20a_init_cg_mode(g, ELCG_MODE, ELCG_RUN);
|
||||
|
||||
/* enable fifo access */
|
||||
gk20a_writel(g, gr_gpfifo_ctl_r(),
|
||||
@@ -5210,11 +5244,9 @@ int gk20a_enable_gr_hw(struct gk20a *g)
|
||||
static void gr_gk20a_enable_elcg(struct gk20a *g)
|
||||
{
|
||||
if (g->elcg_enabled) {
|
||||
gr_gk20a_init_elcg_mode(g, ELCG_AUTO, ENGINE_GR_GK20A);
|
||||
gr_gk20a_init_elcg_mode(g, ELCG_AUTO, ENGINE_CE2_GK20A);
|
||||
gr_gk20a_init_cg_mode(g, ELCG_MODE, ELCG_AUTO);
|
||||
} else {
|
||||
gr_gk20a_init_elcg_mode(g, ELCG_RUN, ENGINE_GR_GK20A);
|
||||
gr_gk20a_init_elcg_mode(g, ELCG_RUN, ENGINE_CE2_GK20A);
|
||||
gr_gk20a_init_cg_mode(g, ELCG_MODE, ELCG_RUN);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6106,6 +6138,7 @@ int gk20a_gr_isr(struct gk20a *g)
|
||||
u32 gr_intr = gk20a_readl(g, gr_intr_r());
|
||||
struct channel_gk20a *ch = NULL;
|
||||
int tsgid = NVGPU_INVALID_TSG_ID;
|
||||
u32 gr_engine_id;
|
||||
|
||||
gk20a_dbg_fn("");
|
||||
gk20a_dbg(gpu_dbg_intr, "pgraph intr %08x", gr_intr);
|
||||
@@ -6113,6 +6146,8 @@ int gk20a_gr_isr(struct gk20a *g)
|
||||
if (!gr_intr)
|
||||
return 0;
|
||||
|
||||
gr_engine_id = gk20a_fifo_get_gr_engine_id(g);
|
||||
|
||||
grfifo_ctl = gk20a_readl(g, gr_gpfifo_ctl_r());
|
||||
grfifo_ctl &= ~gr_gpfifo_ctl_semaphore_access_f(1);
|
||||
grfifo_ctl &= ~gr_gpfifo_ctl_access_f(1);
|
||||
@@ -6283,13 +6318,13 @@ int gk20a_gr_isr(struct gk20a *g)
|
||||
|
||||
if (need_reset) {
|
||||
if (tsgid != NVGPU_INVALID_TSG_ID)
|
||||
gk20a_fifo_recover(g, BIT(ENGINE_GR_GK20A),
|
||||
gk20a_fifo_recover(g, BIT(gr_engine_id),
|
||||
tsgid, true, true, true);
|
||||
else if (ch)
|
||||
gk20a_fifo_recover(g, BIT(ENGINE_GR_GK20A),
|
||||
gk20a_fifo_recover(g, BIT(gr_engine_id),
|
||||
ch->hw_chid, false, true, true);
|
||||
else
|
||||
gk20a_fifo_recover(g, BIT(ENGINE_GR_GK20A),
|
||||
gk20a_fifo_recover(g, BIT(gr_engine_id),
|
||||
0, false, false, true);
|
||||
}
|
||||
|
||||
@@ -8441,6 +8476,10 @@ static u32 *gr_gk20a_rop_l2_en_mask(struct gk20a *g)
|
||||
static int gr_gk20a_dump_gr_status_regs(struct gk20a *g,
|
||||
struct gk20a_debug_output *o)
|
||||
{
|
||||
u32 gr_engine_id;
|
||||
|
||||
gr_engine_id = gk20a_fifo_get_gr_engine_id(g);
|
||||
|
||||
gk20a_debug_output(o, "NV_PGRAPH_STATUS: 0x%x\n",
|
||||
gk20a_readl(g, gr_status_r()));
|
||||
gk20a_debug_output(o, "NV_PGRAPH_STATUS1: 0x%x\n",
|
||||
@@ -8460,7 +8499,7 @@ static int gr_gk20a_dump_gr_status_regs(struct gk20a *g,
|
||||
gk20a_debug_output(o, "NV_PGRAPH_FECS_INTR : 0x%x\n",
|
||||
gk20a_readl(g, gr_fecs_intr_r()));
|
||||
gk20a_debug_output(o, "NV_PFIFO_ENGINE_STATUS(GR) : 0x%x\n",
|
||||
gk20a_readl(g, fifo_engine_status_r(ENGINE_GR_GK20A)));
|
||||
gk20a_readl(g, fifo_engine_status_r(gr_engine_id)));
|
||||
gk20a_debug_output(o, "NV_PGRAPH_ACTIVITY0: 0x%x\n",
|
||||
gk20a_readl(g, gr_activity_0_r()));
|
||||
gk20a_debug_output(o, "NV_PGRAPH_ACTIVITY1: 0x%x\n",
|
||||
|
||||
@@ -81,6 +81,12 @@ enum {
|
||||
eUcodeHandshakeMethodFinished
|
||||
};
|
||||
|
||||
enum {
|
||||
ELCG_MODE = (1 << 0),
|
||||
BLCG_MODE = (1 << 1),
|
||||
INVALID_MODE = (1 << 2)
|
||||
};
|
||||
|
||||
enum {
|
||||
ELCG_RUN, /* clk always run, i.e. disable elcg */
|
||||
ELCG_STOP, /* clk is stopped */
|
||||
@@ -476,6 +482,8 @@ int gr_gk20a_fecs_set_reglist_virtual_addr(struct gk20a *g, u64 pmu_va);
|
||||
void gr_gk20a_init_elcg_mode(struct gk20a *g, u32 mode, u32 engine);
|
||||
void gr_gk20a_init_blcg_mode(struct gk20a *g, u32 mode, u32 engine);
|
||||
|
||||
void gr_gk20a_init_cg_mode(struct gk20a *g, u32 cgmode, u32 mode_config);
|
||||
|
||||
/* sm */
|
||||
bool gk20a_gr_sm_debugger_attached(struct gk20a *g);
|
||||
void gk20a_gr_clear_sm_hww(struct gk20a *g,
|
||||
|
||||
@@ -99,6 +99,9 @@ static int gk20a_get_litter_value(struct gk20a *g,
|
||||
case GPU_LIT_ROP_SHARED_BASE:
|
||||
ret = proj_rop_shared_base_v();
|
||||
break;
|
||||
case GPU_LIT_HOST_NUM_ENGINES:
|
||||
ret = proj_host_num_engines_v();
|
||||
break;
|
||||
case GPU_LIT_HOST_NUM_PBDMA:
|
||||
ret = proj_host_num_pbdma_v();
|
||||
break;
|
||||
|
||||
@@ -106,6 +106,10 @@ static inline u32 proj_tpc_in_gpc_shared_base_v(void)
|
||||
{
|
||||
return 0x00001800;
|
||||
}
|
||||
static inline u32 proj_host_num_engines_v(void)
|
||||
{
|
||||
return 0x00000002;
|
||||
}
|
||||
static inline u32 proj_host_num_pbdma_v(void)
|
||||
{
|
||||
return 0x00000001;
|
||||
|
||||
@@ -118,6 +118,22 @@ static inline u32 top_device_info_type_enum_graphics_f(void)
|
||||
{
|
||||
return 0x0;
|
||||
}
|
||||
static inline u32 top_device_info_type_enum_copy0_v(void)
|
||||
{
|
||||
return 0x00000001;
|
||||
}
|
||||
static inline u32 top_device_info_type_enum_copy0_f(void)
|
||||
{
|
||||
return 0x4;
|
||||
}
|
||||
static inline u32 top_device_info_type_enum_copy1_v(void)
|
||||
{
|
||||
return 0x00000002;
|
||||
}
|
||||
static inline u32 top_device_info_type_enum_copy1_f(void)
|
||||
{
|
||||
return 0x8;
|
||||
}
|
||||
static inline u32 top_device_info_type_enum_copy2_v(void)
|
||||
{
|
||||
return 0x00000003;
|
||||
|
||||
@@ -74,6 +74,9 @@ irqreturn_t mc_gk20a_intr_thread_stall(struct gk20a *g)
|
||||
{
|
||||
u32 mc_intr_0;
|
||||
int hw_irq_count;
|
||||
u32 engine_id_idx;
|
||||
u32 active_engine_id = 0;
|
||||
u32 engine_enum = ENGINE_INVAL_GK20A;
|
||||
|
||||
gk20a_dbg(gpu_dbg_intr, "interrupt thread launched");
|
||||
|
||||
@@ -84,11 +87,26 @@ irqreturn_t mc_gk20a_intr_thread_stall(struct gk20a *g)
|
||||
|
||||
gk20a_dbg(gpu_dbg_intr, "stall intr %08x\n", mc_intr_0);
|
||||
|
||||
if (mc_intr_0 & g->fifo.engine_info[ENGINE_GR_GK20A].intr_mask)
|
||||
gr_gk20a_elpg_protected_call(g, gk20a_gr_isr(g));
|
||||
if (mc_intr_0 & g->fifo.engine_info[ENGINE_CE2_GK20A].intr_mask
|
||||
&& g->ops.ce2.isr_stall)
|
||||
g->ops.ce2.isr_stall(g);
|
||||
for (engine_id_idx = 0; engine_id_idx < g->fifo.num_engines; engine_id_idx++) {
|
||||
active_engine_id = g->fifo.active_engines_list[engine_id_idx];
|
||||
|
||||
if (mc_intr_0 & g->fifo.engine_info[active_engine_id].intr_mask) {
|
||||
engine_enum = g->fifo.engine_info[active_engine_id].engine_enum;
|
||||
/* GR Engine */
|
||||
if (engine_enum == ENGINE_GR_GK20A) {
|
||||
gr_gk20a_elpg_protected_call(g, gk20a_gr_isr(g));
|
||||
}
|
||||
|
||||
/* CE Engine */
|
||||
if (((engine_enum == ENGINE_GRCE_GK20A) ||
|
||||
(engine_enum == ENGINE_ASYNC_CE_GK20A)) &&
|
||||
g->ops.ce2.isr_stall){
|
||||
g->ops.ce2.isr_stall(g,
|
||||
g->fifo.engine_info[active_engine_id].inst_id,
|
||||
g->fifo.engine_info[active_engine_id].pri_base);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mc_intr_0 & mc_intr_0_pfifo_pending_f())
|
||||
gk20a_fifo_isr(g);
|
||||
if (mc_intr_0 & mc_intr_0_pmu_pending_f())
|
||||
@@ -120,6 +138,9 @@ irqreturn_t mc_gk20a_intr_thread_nonstall(struct gk20a *g)
|
||||
{
|
||||
u32 mc_intr_1;
|
||||
int hw_irq_count;
|
||||
u32 engine_id_idx;
|
||||
u32 active_engine_id = 0;
|
||||
u32 engine_enum = ENGINE_INVAL_GK20A;
|
||||
|
||||
gk20a_dbg(gpu_dbg_intr, "interrupt thread launched");
|
||||
|
||||
@@ -132,11 +153,27 @@ irqreturn_t mc_gk20a_intr_thread_nonstall(struct gk20a *g)
|
||||
gk20a_fifo_nonstall_isr(g);
|
||||
if (mc_intr_1 & mc_intr_0_priv_ring_pending_f())
|
||||
gk20a_priv_ring_isr(g);
|
||||
if (mc_intr_1 & g->fifo.engine_info[ENGINE_GR_GK20A].intr_mask)
|
||||
gk20a_gr_nonstall_isr(g);
|
||||
if (mc_intr_1 & g->fifo.engine_info[ENGINE_CE2_GK20A].intr_mask
|
||||
&& g->ops.ce2.isr_nonstall)
|
||||
g->ops.ce2.isr_nonstall(g);
|
||||
|
||||
for (engine_id_idx = 0; engine_id_idx < g->fifo.num_engines; engine_id_idx++) {
|
||||
active_engine_id = g->fifo.active_engines_list[engine_id_idx];
|
||||
|
||||
if (mc_intr_1 & g->fifo.engine_info[active_engine_id].intr_mask) {
|
||||
engine_enum = g->fifo.engine_info[active_engine_id].engine_enum;
|
||||
/* GR Engine */
|
||||
if (engine_enum == ENGINE_GR_GK20A) {
|
||||
gk20a_gr_nonstall_isr(g);
|
||||
}
|
||||
|
||||
/* CE Engine */
|
||||
if (((engine_enum == ENGINE_GRCE_GK20A) ||
|
||||
(engine_enum == ENGINE_ASYNC_CE_GK20A)) &&
|
||||
g->ops.ce2.isr_nonstall) {
|
||||
g->ops.ce2.isr_nonstall(g,
|
||||
g->fifo.engine_info[active_engine_id].inst_id,
|
||||
g->fifo.engine_info[active_engine_id].pri_base);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* sync handled irq counter before re-enabling interrupts */
|
||||
atomic_set(&g->sw_irq_nonstall_last_handled, hw_irq_count);
|
||||
|
||||
@@ -3061,8 +3061,12 @@ int gk20a_init_pmu_bind_fecs(struct gk20a *g)
|
||||
struct pmu_cmd cmd;
|
||||
u32 desc;
|
||||
int err = 0;
|
||||
u32 gr_engine_id;
|
||||
|
||||
gk20a_dbg_fn("");
|
||||
|
||||
gr_engine_id = gk20a_fifo_get_gr_engine_id(g);
|
||||
|
||||
memset(&cmd, 0, sizeof(struct pmu_cmd));
|
||||
cmd.hdr.unit_id = PMU_UNIT_PG;
|
||||
cmd.hdr.size = PMU_CMD_HDR_SIZE +
|
||||
@@ -3070,7 +3074,7 @@ int gk20a_init_pmu_bind_fecs(struct gk20a *g)
|
||||
g->ops.pmu_ver.pg_cmd_eng_buf_load_set_cmd_type(&cmd.cmd.pg,
|
||||
PMU_PG_CMD_ID_ENG_BUF_LOAD);
|
||||
g->ops.pmu_ver.pg_cmd_eng_buf_load_set_engine_id(&cmd.cmd.pg,
|
||||
ENGINE_GR_GK20A);
|
||||
gr_engine_id);
|
||||
g->ops.pmu_ver.pg_cmd_eng_buf_load_set_buf_idx(&cmd.cmd.pg,
|
||||
PMU_PGENG_GR_BUFFER_IDX_FECS);
|
||||
g->ops.pmu_ver.pg_cmd_eng_buf_load_set_buf_size(&cmd.cmd.pg,
|
||||
@@ -3095,6 +3099,9 @@ static void pmu_setup_hw_load_zbc(struct gk20a *g)
|
||||
struct pmu_gk20a *pmu = &g->pmu;
|
||||
struct pmu_cmd cmd;
|
||||
u32 desc;
|
||||
u32 gr_engine_id;
|
||||
|
||||
gr_engine_id = gk20a_fifo_get_gr_engine_id(g);
|
||||
|
||||
memset(&cmd, 0, sizeof(struct pmu_cmd));
|
||||
cmd.hdr.unit_id = PMU_UNIT_PG;
|
||||
@@ -3103,7 +3110,7 @@ static void pmu_setup_hw_load_zbc(struct gk20a *g)
|
||||
g->ops.pmu_ver.pg_cmd_eng_buf_load_set_cmd_type(&cmd.cmd.pg,
|
||||
PMU_PG_CMD_ID_ENG_BUF_LOAD);
|
||||
g->ops.pmu_ver.pg_cmd_eng_buf_load_set_engine_id(&cmd.cmd.pg,
|
||||
ENGINE_GR_GK20A);
|
||||
gr_engine_id);
|
||||
g->ops.pmu_ver.pg_cmd_eng_buf_load_set_buf_idx(&cmd.cmd.pg,
|
||||
PMU_PGENG_GR_BUFFER_IDX_ZBC);
|
||||
g->ops.pmu_ver.pg_cmd_eng_buf_load_set_buf_size(&cmd.cmd.pg,
|
||||
@@ -3288,20 +3295,23 @@ static int pmu_init_powergating(struct gk20a *g)
|
||||
struct pmu_gk20a *pmu = &g->pmu;
|
||||
struct pmu_cmd cmd;
|
||||
u32 seq;
|
||||
u32 gr_engine_id;
|
||||
|
||||
gk20a_dbg_fn("");
|
||||
|
||||
gr_engine_id = gk20a_fifo_get_gr_engine_id(g);
|
||||
|
||||
if (tegra_cpu_is_asim()) {
|
||||
/* TBD: calculate threshold for silicon */
|
||||
gk20a_writel(g, pwr_pmu_pg_idlefilth_r(ENGINE_GR_GK20A),
|
||||
gk20a_writel(g, pwr_pmu_pg_idlefilth_r(gr_engine_id),
|
||||
PMU_PG_IDLE_THRESHOLD_SIM);
|
||||
gk20a_writel(g, pwr_pmu_pg_ppuidlefilth_r(ENGINE_GR_GK20A),
|
||||
gk20a_writel(g, pwr_pmu_pg_ppuidlefilth_r(gr_engine_id),
|
||||
PMU_PG_POST_POWERUP_IDLE_THRESHOLD_SIM);
|
||||
} else {
|
||||
/* TBD: calculate threshold for silicon */
|
||||
gk20a_writel(g, pwr_pmu_pg_idlefilth_r(ENGINE_GR_GK20A),
|
||||
gk20a_writel(g, pwr_pmu_pg_idlefilth_r(gr_engine_id),
|
||||
PMU_PG_IDLE_THRESHOLD);
|
||||
gk20a_writel(g, pwr_pmu_pg_ppuidlefilth_r(ENGINE_GR_GK20A),
|
||||
gk20a_writel(g, pwr_pmu_pg_ppuidlefilth_r(gr_engine_id),
|
||||
PMU_PG_POST_POWERUP_IDLE_THRESHOLD);
|
||||
}
|
||||
|
||||
@@ -3316,7 +3326,7 @@ static int pmu_init_powergating(struct gk20a *g)
|
||||
cmd.hdr.unit_id = PMU_UNIT_PG;
|
||||
cmd.hdr.size = PMU_CMD_HDR_SIZE + sizeof(struct pmu_pg_cmd_elpg_cmd);
|
||||
cmd.cmd.pg.elpg_cmd.cmd_type = PMU_PG_CMD_ID_ELPG_CMD;
|
||||
cmd.cmd.pg.elpg_cmd.engine_id = ENGINE_GR_GK20A;
|
||||
cmd.cmd.pg.elpg_cmd.engine_id = gr_engine_id;
|
||||
cmd.cmd.pg.elpg_cmd.cmd = PMU_PG_ELPG_CMD_INIT;
|
||||
|
||||
gk20a_dbg_pmu("cmd post PMU_PG_ELPG_CMD_INIT");
|
||||
@@ -3329,7 +3339,7 @@ static int pmu_init_powergating(struct gk20a *g)
|
||||
cmd.hdr.unit_id = PMU_UNIT_PG;
|
||||
cmd.hdr.size = PMU_CMD_HDR_SIZE + sizeof(struct pmu_pg_cmd_stat);
|
||||
cmd.cmd.pg.stat.cmd_type = PMU_PG_CMD_ID_PG_STAT;
|
||||
cmd.cmd.pg.stat.engine_id = ENGINE_GR_GK20A;
|
||||
cmd.cmd.pg.stat.engine_id = gr_engine_id;
|
||||
cmd.cmd.pg.stat.sub_cmd_id = PMU_PG_STAT_CMD_ALLOC_DMEM;
|
||||
cmd.cmd.pg.stat.data = 0;
|
||||
|
||||
@@ -3344,7 +3354,7 @@ static int pmu_init_powergating(struct gk20a *g)
|
||||
cmd.hdr.unit_id = PMU_UNIT_PG;
|
||||
cmd.hdr.size = PMU_CMD_HDR_SIZE + sizeof(struct pmu_pg_cmd_elpg_cmd);
|
||||
cmd.cmd.pg.elpg_cmd.cmd_type = PMU_PG_CMD_ID_ELPG_CMD;
|
||||
cmd.cmd.pg.elpg_cmd.engine_id = ENGINE_GR_GK20A;
|
||||
cmd.cmd.pg.elpg_cmd.engine_id = gr_engine_id;
|
||||
cmd.cmd.pg.elpg_cmd.cmd = PMU_PG_ELPG_CMD_DISALLOW;
|
||||
|
||||
gk20a_dbg_pmu("cmd post PMU_PG_ELPG_CMD_DISALLOW");
|
||||
@@ -4429,14 +4439,17 @@ static int gk20a_pmu_enable_elpg_locked(struct gk20a *g)
|
||||
struct pmu_gk20a *pmu = &g->pmu;
|
||||
struct pmu_cmd cmd;
|
||||
u32 seq, status;
|
||||
u32 gr_engine_id;
|
||||
|
||||
gk20a_dbg_fn("");
|
||||
|
||||
gr_engine_id = gk20a_fifo_get_gr_engine_id(g);
|
||||
|
||||
memset(&cmd, 0, sizeof(struct pmu_cmd));
|
||||
cmd.hdr.unit_id = PMU_UNIT_PG;
|
||||
cmd.hdr.size = PMU_CMD_HDR_SIZE + sizeof(struct pmu_pg_cmd_elpg_cmd);
|
||||
cmd.cmd.pg.elpg_cmd.cmd_type = PMU_PG_CMD_ID_ELPG_CMD;
|
||||
cmd.cmd.pg.elpg_cmd.engine_id = ENGINE_GR_GK20A;
|
||||
cmd.cmd.pg.elpg_cmd.engine_id = gr_engine_id;
|
||||
cmd.cmd.pg.elpg_cmd.cmd = PMU_PG_ELPG_CMD_ALLOW;
|
||||
|
||||
/* no need to wait ack for ELPG enable but set pending to sync
|
||||
@@ -4503,9 +4516,12 @@ int gk20a_pmu_disable_elpg(struct gk20a *g)
|
||||
struct pmu_cmd cmd;
|
||||
u32 seq;
|
||||
int ret = 0;
|
||||
u32 gr_engine_id;
|
||||
|
||||
gk20a_dbg_fn("");
|
||||
|
||||
gr_engine_id = gk20a_fifo_get_gr_engine_id(g);
|
||||
|
||||
if (!support_gk20a_pmu(g->dev))
|
||||
return ret;
|
||||
|
||||
@@ -4553,7 +4569,7 @@ int gk20a_pmu_disable_elpg(struct gk20a *g)
|
||||
cmd.hdr.unit_id = PMU_UNIT_PG;
|
||||
cmd.hdr.size = PMU_CMD_HDR_SIZE + sizeof(struct pmu_pg_cmd_elpg_cmd);
|
||||
cmd.cmd.pg.elpg_cmd.cmd_type = PMU_PG_CMD_ID_ELPG_CMD;
|
||||
cmd.cmd.pg.elpg_cmd.engine_id = ENGINE_GR_GK20A;
|
||||
cmd.cmd.pg.elpg_cmd.engine_id = gr_engine_id;
|
||||
cmd.cmd.pg.elpg_cmd.cmd = PMU_PG_ELPG_CMD_DISALLOW;
|
||||
|
||||
pmu->elpg_stat = PMU_ELPG_STAT_OFF_PENDING;
|
||||
|
||||
107
drivers/gpu/nvgpu/gm206/ce_gm206.c
Normal file
107
drivers/gpu/nvgpu/gm206/ce_gm206.c
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* GM206 Copy Engine.
|
||||
*
|
||||
* Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program.
|
||||
*/
|
||||
|
||||
/*TODO: remove uncecessary */
|
||||
#include "gk20a/gk20a.h"
|
||||
#include "ce_gm206.h"
|
||||
|
||||
/*TODO: remove uncecessary */
|
||||
#include <linux/delay.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <trace/events/gk20a.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/nvhost.h>
|
||||
|
||||
#include "gk20a/debug_gk20a.h"
|
||||
#include "gk20a/semaphore_gk20a.h"
|
||||
#include "hw_ce2_gm206.h"
|
||||
#include "hw_pbdma_gm206.h"
|
||||
#include "hw_ccsr_gm206.h"
|
||||
#include "hw_ram_gm206.h"
|
||||
#include "hw_top_gm206.h"
|
||||
#include "hw_mc_gm206.h"
|
||||
#include "hw_gr_gm206.h"
|
||||
|
||||
/* TODO: We need generic way for query the intr_status register offset.
|
||||
* As of now, there is no way to query this information from dev_ceN_pri.h */
|
||||
#define COP_INTR_STATUS_OFFSET 0x908
|
||||
|
||||
static u32 ce_nonblockpipe_isr(struct gk20a *g, u32 fifo_intr, u32 inst_id)
|
||||
{
|
||||
gk20a_dbg(gpu_dbg_intr, "ce non-blocking pipe interrupt\n");
|
||||
|
||||
return ce2_intr_status_nonblockpipe_pending_f();
|
||||
}
|
||||
|
||||
static u32 ce_blockpipe_isr(struct gk20a *g, u32 fifo_intr, u32 inst_id)
|
||||
{
|
||||
gk20a_dbg(gpu_dbg_intr, "ce blocking pipe interrupt\n");
|
||||
|
||||
return ce2_intr_status_blockpipe_pending_f();
|
||||
}
|
||||
|
||||
static u32 ce_launcherr_isr(struct gk20a *g, u32 fifo_intr, u32 inst_id)
|
||||
{
|
||||
gk20a_dbg(gpu_dbg_intr, "ce launch error interrupt\n");
|
||||
|
||||
return ce2_intr_status_launcherr_pending_f();
|
||||
}
|
||||
|
||||
void gm206_ce_isr(struct gk20a *g, u32 inst_id, u32 pri_base)
|
||||
{
|
||||
u32 ce_intr_status_reg = (pri_base + COP_INTR_STATUS_OFFSET);
|
||||
u32 ce_intr = gk20a_readl(g, ce_intr_status_reg);
|
||||
u32 clear_intr = 0;
|
||||
|
||||
gk20a_dbg(gpu_dbg_intr, "ce isr %08x %08x\n", ce_intr, inst_id);
|
||||
|
||||
/* clear blocking interrupts: they exibit broken behavior */
|
||||
if (ce_intr & ce2_intr_status_blockpipe_pending_f())
|
||||
clear_intr |= ce_blockpipe_isr(g, ce_intr, inst_id);
|
||||
|
||||
if (ce_intr & ce2_intr_status_launcherr_pending_f())
|
||||
clear_intr |= ce_launcherr_isr(g, ce_intr, inst_id);
|
||||
|
||||
gk20a_writel(g, ce_intr_status_reg, clear_intr);
|
||||
return;
|
||||
}
|
||||
|
||||
void gm206_ce_nonstall_isr(struct gk20a *g, u32 inst_id, u32 pri_base)
|
||||
{
|
||||
u32 ce_intr_status_reg = (pri_base + COP_INTR_STATUS_OFFSET);
|
||||
u32 ce_intr = gk20a_readl(g, ce_intr_status_reg);
|
||||
|
||||
gk20a_dbg(gpu_dbg_intr, "ce nonstall isr %08x %08x\n", ce_intr, inst_id);
|
||||
|
||||
if (ce_intr & ce2_intr_status_nonblockpipe_pending_f()) {
|
||||
gk20a_writel(g, ce_intr_status_reg,
|
||||
ce_nonblockpipe_isr(g, ce_intr, inst_id));
|
||||
|
||||
/* wake threads waiting in this channel */
|
||||
gk20a_channel_semaphore_wakeup(g, true);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void gm206_init_ce(struct gpu_ops *gops)
|
||||
{
|
||||
gops->ce2.isr_stall = gm206_ce_isr;
|
||||
gops->ce2.isr_nonstall = gm206_ce_nonstall_isr;
|
||||
}
|
||||
26
drivers/gpu/nvgpu/gm206/ce_gm206.h
Normal file
26
drivers/gpu/nvgpu/gm206/ce_gm206.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* GM206 copy engine.
|
||||
*
|
||||
* Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program.
|
||||
*/
|
||||
#ifndef __CE_GM206_H__
|
||||
#define __CE_GM206_H__
|
||||
|
||||
#include "gk20a/channel_gk20a.h"
|
||||
#include "gk20a/tsg_gk20a.h"
|
||||
|
||||
void gm206_init_ce(struct gpu_ops *gops);
|
||||
|
||||
#endif /*__CE2_GM20B_H__*/
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "gm20b/fifo_gm20b.h"
|
||||
#include "fifo_gm206.h"
|
||||
#include "hw_ccsr_gm206.h"
|
||||
#include "hw_fifo_gm206.h"
|
||||
|
||||
static u32 gm206_fifo_get_num_fifos(struct gk20a *g)
|
||||
{
|
||||
@@ -28,4 +29,5 @@ void gm206_init_fifo(struct gpu_ops *gops)
|
||||
{
|
||||
gm20b_init_fifo(gops);
|
||||
gops->fifo.get_num_fifos = gm206_fifo_get_num_fifos;
|
||||
gops->fifo.eng_runlist_base_size = fifo_eng_runlist_base__size_1_v;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include "gm20b/mc_gm20b.h"
|
||||
#include "gm20b/ltc_gm20b.h"
|
||||
#include "gm20b/mm_gm20b.h"
|
||||
#include "gm20b/ce2_gm20b.h"
|
||||
#include "ce_gm206.h"
|
||||
#include "gm20b/fb_gm20b.h"
|
||||
#include "gm20b/pmu_gm20b.h"
|
||||
#include "gm20b/gr_gm20b.h"
|
||||
@@ -142,6 +142,9 @@ static int gm206_get_litter_value(struct gk20a *g,
|
||||
case GPU_LIT_ROP_SHARED_BASE:
|
||||
ret = proj_rop_shared_base_v();
|
||||
break;
|
||||
case GPU_LIT_HOST_NUM_ENGINES:
|
||||
ret = proj_host_num_engines_v();
|
||||
break;
|
||||
case GPU_LIT_HOST_NUM_PBDMA:
|
||||
ret = proj_host_num_pbdma_v();
|
||||
break;
|
||||
@@ -183,7 +186,7 @@ int gm206_init_hal(struct gk20a *g)
|
||||
gm20b_init_fb(gops);
|
||||
g->ops.fb.set_use_full_comp_tag_line = NULL;
|
||||
gm206_init_fifo(gops);
|
||||
gm20b_init_ce2(gops);
|
||||
gm206_init_ce(gops);
|
||||
gm20b_init_gr_ctx(gops);
|
||||
gm20b_init_mm(gops);
|
||||
gm206_init_pmu_ops(gops);
|
||||
|
||||
@@ -106,6 +106,10 @@ static inline u32 proj_tpc_in_gpc_shared_base_v(void)
|
||||
{
|
||||
return 0x00001800;
|
||||
}
|
||||
static inline u32 proj_host_num_engines_v(void)
|
||||
{
|
||||
return 0x00000008;
|
||||
}
|
||||
static inline u32 proj_host_num_pbdma_v(void)
|
||||
{
|
||||
return 0x00000003;
|
||||
|
||||
@@ -146,6 +146,22 @@ static inline u32 top_device_info_type_enum_copy0_f(void)
|
||||
{
|
||||
return 0x4;
|
||||
}
|
||||
static inline u32 top_device_info_type_enum_copy1_v(void)
|
||||
{
|
||||
return 0x00000002;
|
||||
}
|
||||
static inline u32 top_device_info_type_enum_copy1_f(void)
|
||||
{
|
||||
return 0x8;
|
||||
}
|
||||
static inline u32 top_device_info_type_enum_copy2_v(void)
|
||||
{
|
||||
return 0x00000003;
|
||||
}
|
||||
static inline u32 top_device_info_type_enum_copy2_f(void)
|
||||
{
|
||||
return 0xc;
|
||||
}
|
||||
static inline u32 top_device_info_entry_v(u32 r)
|
||||
{
|
||||
return (r >> 0) & 0x3;
|
||||
|
||||
@@ -49,12 +49,14 @@ static void channel_gm20b_bind(struct channel_gk20a *c)
|
||||
static inline u32 gm20b_engine_id_to_mmu_id(struct gk20a *g, u32 engine_id)
|
||||
{
|
||||
u32 fault_id = ~0;
|
||||
struct fifo_engine_info_gk20a *engine_info;
|
||||
|
||||
if (engine_id < ENGINE_INVAL_GK20A) {
|
||||
struct fifo_engine_info_gk20a *info =
|
||||
&g->fifo.engine_info[engine_id];
|
||||
engine_info = gk20a_fifo_get_engine_info(g, engine_id);
|
||||
|
||||
fault_id = info->fault_id;
|
||||
if (engine_info) {
|
||||
fault_id = engine_info->fault_id;
|
||||
} else {
|
||||
gk20a_err(g->dev, "engine_id is not in active list/invalid %d", engine_id);
|
||||
}
|
||||
return fault_id;
|
||||
}
|
||||
@@ -72,7 +74,7 @@ static void gm20b_fifo_trigger_mmu_fault(struct gk20a *g,
|
||||
for_each_set_bit(engine_id, &engine_ids, 32) {
|
||||
u32 engine_mmu_fault_id;
|
||||
|
||||
if (engine_id > g->fifo.max_engines) {
|
||||
if (!gk20a_fifo_is_valid_engine_id(g, engine_id)) {
|
||||
gk20a_err(dev_from_gk20a(g),
|
||||
"faulting unknown engine %ld", engine_id);
|
||||
} else {
|
||||
@@ -109,7 +111,7 @@ static u32 gm20b_fifo_get_num_fifos(struct gk20a *g)
|
||||
return ccsr_channel__size_1_v();
|
||||
}
|
||||
|
||||
void gm20b_device_info_data_parse(struct gk20a *g,
|
||||
static void gm20b_device_info_data_parse(struct gk20a *g,
|
||||
u32 table_entry, u32 *inst_id,
|
||||
u32 *pri_base, u32 *fault_id)
|
||||
{
|
||||
@@ -152,4 +154,5 @@ void gm20b_init_fifo(struct gpu_ops *gops)
|
||||
gops->fifo.force_reset_ch = gk20a_fifo_force_reset_ch;
|
||||
gops->fifo.engine_enum_from_type = gk20a_fifo_engine_enum_from_type;
|
||||
gops->fifo.device_info_data_parse = gm20b_device_info_data_parse;
|
||||
gops->fifo.eng_runlist_base_size = fifo_eng_runlist_base__size_1_v;
|
||||
}
|
||||
|
||||
@@ -855,6 +855,9 @@ static int gr_gm20b_dump_gr_status_regs(struct gk20a *g,
|
||||
struct gk20a_debug_output *o)
|
||||
{
|
||||
struct gr_gk20a *gr = &g->gr;
|
||||
u32 gr_engine_id;
|
||||
|
||||
gr_engine_id = gk20a_fifo_get_gr_engine_id(g);
|
||||
|
||||
gk20a_debug_output(o, "NV_PGRAPH_STATUS: 0x%x\n",
|
||||
gk20a_readl(g, gr_status_r()));
|
||||
@@ -875,7 +878,7 @@ static int gr_gm20b_dump_gr_status_regs(struct gk20a *g,
|
||||
gk20a_debug_output(o, "NV_PGRAPH_FECS_INTR : 0x%x\n",
|
||||
gk20a_readl(g, gr_fecs_intr_r()));
|
||||
gk20a_debug_output(o, "NV_PFIFO_ENGINE_STATUS(GR) : 0x%x\n",
|
||||
gk20a_readl(g, fifo_engine_status_r(ENGINE_GR_GK20A)));
|
||||
gk20a_readl(g, fifo_engine_status_r(gr_engine_id)));
|
||||
gk20a_debug_output(o, "NV_PGRAPH_ACTIVITY0: 0x%x\n",
|
||||
gk20a_readl(g, gr_activity_0_r()));
|
||||
gk20a_debug_output(o, "NV_PGRAPH_ACTIVITY1: 0x%x\n",
|
||||
|
||||
@@ -140,6 +140,9 @@ static int gm20b_get_litter_value(struct gk20a *g,
|
||||
case GPU_LIT_ROP_SHARED_BASE:
|
||||
ret = proj_rop_shared_base_v();
|
||||
break;
|
||||
case GPU_LIT_HOST_NUM_ENGINES:
|
||||
ret = proj_host_num_engines_v();
|
||||
break;
|
||||
case GPU_LIT_HOST_NUM_PBDMA:
|
||||
ret = proj_host_num_pbdma_v();
|
||||
break;
|
||||
|
||||
@@ -106,6 +106,10 @@ static inline u32 proj_tpc_in_gpc_shared_base_v(void)
|
||||
{
|
||||
return 0x00001800;
|
||||
}
|
||||
static inline u32 proj_host_num_engines_v(void)
|
||||
{
|
||||
return 0x00000002;
|
||||
}
|
||||
static inline u32 proj_host_num_pbdma_v(void)
|
||||
{
|
||||
return 0x00000001;
|
||||
|
||||
@@ -138,6 +138,22 @@ static inline u32 top_device_info_type_enum_graphics_f(void)
|
||||
{
|
||||
return 0x0;
|
||||
}
|
||||
static inline u32 top_device_info_type_enum_copy0_v(void)
|
||||
{
|
||||
return 0x00000001;
|
||||
}
|
||||
static inline u32 top_device_info_type_enum_copy0_f(void)
|
||||
{
|
||||
return 0x4;
|
||||
}
|
||||
static inline u32 top_device_info_type_enum_copy1_v(void)
|
||||
{
|
||||
return 0x00000002;
|
||||
}
|
||||
static inline u32 top_device_info_type_enum_copy1_f(void)
|
||||
{
|
||||
return 0x8;
|
||||
}
|
||||
static inline u32 top_device_info_type_enum_copy2_v(void)
|
||||
{
|
||||
return 0x00000003;
|
||||
|
||||
@@ -163,60 +163,52 @@ static int init_engine_info(struct fifo_gk20a *f)
|
||||
|
||||
static int init_runlist(struct gk20a *g, struct fifo_gk20a *f)
|
||||
{
|
||||
struct fifo_engine_info_gk20a *engine_info;
|
||||
struct fifo_runlist_info_gk20a *runlist;
|
||||
struct device *d = dev_from_gk20a(g);
|
||||
u32 runlist_id;
|
||||
s32 runlist_id = -1;
|
||||
u32 i;
|
||||
u64 runlist_size;
|
||||
|
||||
gk20a_dbg_fn("");
|
||||
|
||||
f->max_runlists = fifo_eng_runlist_base__size_1_v();
|
||||
f->max_runlists = g->ops.fifo.eng_runlist_base_size();
|
||||
f->runlist_info = kzalloc(sizeof(struct fifo_runlist_info_gk20a) *
|
||||
f->max_runlists, GFP_KERNEL);
|
||||
if (!f->runlist_info)
|
||||
goto clean_up;
|
||||
goto clean_up_runlist;
|
||||
|
||||
engine_info = f->engine_info + ENGINE_GR_GK20A;
|
||||
runlist_id = engine_info->runlist_id;
|
||||
runlist = &f->runlist_info[runlist_id];
|
||||
memset(f->runlist_info, 0, (sizeof(struct fifo_runlist_info_gk20a) *
|
||||
f->max_runlists));
|
||||
|
||||
runlist->active_channels =
|
||||
kzalloc(DIV_ROUND_UP(f->num_channels, BITS_PER_BYTE),
|
||||
GFP_KERNEL);
|
||||
if (!runlist->active_channels)
|
||||
goto clean_up_runlist_info;
|
||||
for (runlist_id = 0; runlist_id < f->max_runlists; runlist_id++) {
|
||||
runlist = &f->runlist_info[runlist_id];
|
||||
|
||||
runlist_size = sizeof(u16) * f->num_channels;
|
||||
for (i = 0; i < MAX_RUNLIST_BUFFERS; i++) {
|
||||
int err = gk20a_gmmu_alloc(g, runlist_size, &runlist->mem[i]);
|
||||
if (err) {
|
||||
dev_err(d, "memory allocation failed\n");
|
||||
runlist->active_channels =
|
||||
kzalloc(DIV_ROUND_UP(f->num_channels, BITS_PER_BYTE),
|
||||
GFP_KERNEL);
|
||||
if (!runlist->active_channels)
|
||||
goto clean_up_runlist;
|
||||
}
|
||||
}
|
||||
mutex_init(&runlist->mutex);
|
||||
|
||||
/* None of buffers is pinned if this value doesn't change.
|
||||
Otherwise, one of them (cur_buffer) must have been pinned. */
|
||||
runlist->cur_buffer = MAX_RUNLIST_BUFFERS;
|
||||
runlist_size = sizeof(u16) * f->num_channels;
|
||||
for (i = 0; i < MAX_RUNLIST_BUFFERS; i++) {
|
||||
int err = gk20a_gmmu_alloc(g, runlist_size, &runlist->mem[i]);
|
||||
if (err) {
|
||||
dev_err(d, "memory allocation failed\n");
|
||||
goto clean_up_runlist;
|
||||
}
|
||||
}
|
||||
mutex_init(&runlist->mutex);
|
||||
|
||||
/* None of buffers is pinned if this value doesn't change.
|
||||
Otherwise, one of them (cur_buffer) must have been pinned. */
|
||||
runlist->cur_buffer = MAX_RUNLIST_BUFFERS;
|
||||
}
|
||||
|
||||
gk20a_dbg_fn("done");
|
||||
return 0;
|
||||
|
||||
clean_up_runlist:
|
||||
for (i = 0; i < MAX_RUNLIST_BUFFERS; i++)
|
||||
gk20a_gmmu_free(g, &runlist->mem[i]);
|
||||
|
||||
clean_up_runlist_info:
|
||||
kfree(runlist->active_channels);
|
||||
runlist->active_channels = NULL;
|
||||
|
||||
kfree(f->runlist_info);
|
||||
f->runlist_info = NULL;
|
||||
|
||||
clean_up:
|
||||
gk20a_fifo_delete_runlist(f);
|
||||
gk20a_dbg_fn("fail");
|
||||
return -ENOMEM;
|
||||
}
|
||||
@@ -243,7 +235,7 @@ static int vgpu_init_fifo_setup_sw(struct gk20a *g)
|
||||
if (err)
|
||||
return -ENXIO;
|
||||
|
||||
f->max_engines = ENGINE_INVAL_GK20A;
|
||||
f->max_engines = nvgpu_get_litter_value(g, GPU_LIT_HOST_NUM_ENGINES);
|
||||
|
||||
f->userd_entry_size = 1 << ram_userd_base_shift_v();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user