mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-25 02:52:51 +03:00
gpu: nvgpu: move ctxsw related code to gr falcon
In this CL, following ctxsw related code is moved to hal gr falcon. 1. gr_gk20a_wait_ctxsw_ready -> gm20b_gr_falcon_wait_ctxsw_ready 2. gr_gk20a_submit_fecs_method_op -> gm20b_gr_falcon_submit_fecs_method_op 3. gr_gk20a_submit_fecs_sideband_method_op-> gm20b_gr_falcon_submit_fecs_sideband_method_op Above functions are populated with following gr.falcon hals and called from the current code as required: int (*wait_ctxsw_ready)(struct gk20a *g); int (*submit_fecs_method_op)(struct gk20a *g, struct fecs_method_op_gk20a op, bool sleepduringwait); int (*submit_fecs_sideband_method_op)(struct gk20a *g, struct fecs_method_op_gk20a op); Following static function also moved to gr_gk20a.c to hal gr falcon. gr_gk20a_ctx_wait_ucode -> gm20b_gr_falcon_ctx_wait_ucode JIRA NVGPU-1881 Change-Id: Icb4238dcacaf46ecfcada8bc8dcdeb68b6278bab Signed-off-by: Seshendra Gadagottu <sgadagottu@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/2085189 Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com> GVS: Gerrit_Virtual_Submit Reviewed-by: Vinod Gopalakrishnakurup <vinodg@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
committed by
mobile promotions
parent
0e342a28b4
commit
1c8e8a53ec
@@ -176,212 +176,10 @@ static void gr_report_ctxsw_error(struct gk20a *g, u32 err_type, u32 chid,
|
||||
}
|
||||
}
|
||||
}
|
||||
int gr_gk20a_ctx_wait_ucode(struct gk20a *g, u32 mailbox_id,
|
||||
u32 *mailbox_ret, u32 opc_success,
|
||||
u32 mailbox_ok, u32 opc_fail,
|
||||
u32 mailbox_fail, bool sleepduringwait)
|
||||
{
|
||||
struct nvgpu_timeout timeout;
|
||||
u32 delay = GR_FECS_POLL_INTERVAL;
|
||||
enum wait_ucode_status check = WAIT_UCODE_LOOP;
|
||||
u32 reg;
|
||||
|
||||
nvgpu_log_fn(g, " ");
|
||||
|
||||
if (sleepduringwait) {
|
||||
delay = POLL_DELAY_MIN_US;
|
||||
}
|
||||
|
||||
nvgpu_timeout_init(g, &timeout, nvgpu_get_poll_timeout(g),
|
||||
NVGPU_TIMER_CPU_TIMER);
|
||||
|
||||
while (check == WAIT_UCODE_LOOP) {
|
||||
if (nvgpu_timeout_expired(&timeout) != 0) {
|
||||
check = WAIT_UCODE_TIMEOUT;
|
||||
}
|
||||
|
||||
reg = gk20a_readl(g, gr_fecs_ctxsw_mailbox_r(mailbox_id));
|
||||
|
||||
if (mailbox_ret != NULL) {
|
||||
*mailbox_ret = reg;
|
||||
}
|
||||
|
||||
switch (opc_success) {
|
||||
case GR_IS_UCODE_OP_EQUAL:
|
||||
if (reg == mailbox_ok) {
|
||||
check = WAIT_UCODE_OK;
|
||||
}
|
||||
break;
|
||||
case GR_IS_UCODE_OP_NOT_EQUAL:
|
||||
if (reg != mailbox_ok) {
|
||||
check = WAIT_UCODE_OK;
|
||||
}
|
||||
break;
|
||||
case GR_IS_UCODE_OP_AND:
|
||||
if ((reg & mailbox_ok) != 0U) {
|
||||
check = WAIT_UCODE_OK;
|
||||
}
|
||||
break;
|
||||
case GR_IS_UCODE_OP_LESSER:
|
||||
if (reg < mailbox_ok) {
|
||||
check = WAIT_UCODE_OK;
|
||||
}
|
||||
break;
|
||||
case GR_IS_UCODE_OP_LESSER_EQUAL:
|
||||
if (reg <= mailbox_ok) {
|
||||
check = WAIT_UCODE_OK;
|
||||
}
|
||||
break;
|
||||
case GR_IS_UCODE_OP_SKIP:
|
||||
/* do no success check */
|
||||
break;
|
||||
default:
|
||||
nvgpu_err(g,
|
||||
"invalid success opcode 0x%x", opc_success);
|
||||
|
||||
check = WAIT_UCODE_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (opc_fail) {
|
||||
case GR_IS_UCODE_OP_EQUAL:
|
||||
if (reg == mailbox_fail) {
|
||||
check = WAIT_UCODE_ERROR;
|
||||
}
|
||||
break;
|
||||
case GR_IS_UCODE_OP_NOT_EQUAL:
|
||||
if (reg != mailbox_fail) {
|
||||
check = WAIT_UCODE_ERROR;
|
||||
}
|
||||
break;
|
||||
case GR_IS_UCODE_OP_AND:
|
||||
if ((reg & mailbox_fail) != 0U) {
|
||||
check = WAIT_UCODE_ERROR;
|
||||
}
|
||||
break;
|
||||
case GR_IS_UCODE_OP_LESSER:
|
||||
if (reg < mailbox_fail) {
|
||||
check = WAIT_UCODE_ERROR;
|
||||
}
|
||||
break;
|
||||
case GR_IS_UCODE_OP_LESSER_EQUAL:
|
||||
if (reg <= mailbox_fail) {
|
||||
check = WAIT_UCODE_ERROR;
|
||||
}
|
||||
break;
|
||||
case GR_IS_UCODE_OP_SKIP:
|
||||
/* do no check on fail*/
|
||||
break;
|
||||
default:
|
||||
nvgpu_err(g,
|
||||
"invalid fail opcode 0x%x", opc_fail);
|
||||
check = WAIT_UCODE_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
if (sleepduringwait) {
|
||||
nvgpu_usleep_range(delay, delay * 2U);
|
||||
delay = min_t(u32, delay << 1, POLL_DELAY_MAX_US);
|
||||
} else {
|
||||
nvgpu_udelay(delay);
|
||||
}
|
||||
}
|
||||
|
||||
if (check == WAIT_UCODE_TIMEOUT) {
|
||||
nvgpu_err(g,
|
||||
"timeout waiting on mailbox=%d value=0x%08x",
|
||||
mailbox_id, reg);
|
||||
g->ops.gr.falcon.dump_stats(g);
|
||||
gk20a_gr_debug_dump(g);
|
||||
return -1;
|
||||
} else if (check == WAIT_UCODE_ERROR) {
|
||||
nvgpu_err(g,
|
||||
"ucode method failed on mailbox=%d value=0x%08x",
|
||||
mailbox_id, reg);
|
||||
g->ops.gr.falcon.dump_stats(g);
|
||||
return -1;
|
||||
}
|
||||
|
||||
nvgpu_log_fn(g, "done");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The following is a less brittle way to call gr_gk20a_submit_fecs_method(...)
|
||||
* We should replace most, if not all, fecs method calls to this instead. */
|
||||
int gr_gk20a_submit_fecs_method_op(struct gk20a *g,
|
||||
struct fecs_method_op_gk20a op,
|
||||
bool sleepduringwait)
|
||||
{
|
||||
struct gr_gk20a *gr = &g->gr;
|
||||
int ret;
|
||||
|
||||
nvgpu_mutex_acquire(&gr->fecs_mutex);
|
||||
|
||||
if (op.mailbox.id != 0U) {
|
||||
gk20a_writel(g, gr_fecs_ctxsw_mailbox_r(op.mailbox.id),
|
||||
op.mailbox.data);
|
||||
}
|
||||
|
||||
gk20a_writel(g, gr_fecs_ctxsw_mailbox_clear_r(0),
|
||||
gr_fecs_ctxsw_mailbox_clear_value_f(op.mailbox.clr));
|
||||
|
||||
gk20a_writel(g, gr_fecs_method_data_r(), op.method.data);
|
||||
gk20a_writel(g, gr_fecs_method_push_r(),
|
||||
gr_fecs_method_push_adr_f(op.method.addr));
|
||||
|
||||
/* op.mailbox.id == 4 cases require waiting for completion on
|
||||
* for op.mailbox.id == 0 */
|
||||
if (op.mailbox.id == 4U) {
|
||||
op.mailbox.id = 0;
|
||||
}
|
||||
|
||||
ret = gr_gk20a_ctx_wait_ucode(g, op.mailbox.id, op.mailbox.ret,
|
||||
op.cond.ok, op.mailbox.ok,
|
||||
op.cond.fail, op.mailbox.fail,
|
||||
sleepduringwait);
|
||||
if (ret != 0) {
|
||||
nvgpu_err(g,"fecs method: data=0x%08x push adr=0x%08x",
|
||||
op.method.data, op.method.addr);
|
||||
}
|
||||
|
||||
nvgpu_mutex_release(&gr->fecs_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Sideband mailbox writes are done a bit differently */
|
||||
int gr_gk20a_submit_fecs_sideband_method_op(struct gk20a *g,
|
||||
struct fecs_method_op_gk20a op)
|
||||
{
|
||||
struct gr_gk20a *gr = &g->gr;
|
||||
int ret;
|
||||
|
||||
nvgpu_mutex_acquire(&gr->fecs_mutex);
|
||||
|
||||
gk20a_writel(g, gr_fecs_ctxsw_mailbox_clear_r(op.mailbox.id),
|
||||
gr_fecs_ctxsw_mailbox_clear_value_f(op.mailbox.clr));
|
||||
|
||||
gk20a_writel(g, gr_fecs_method_data_r(), op.method.data);
|
||||
gk20a_writel(g, gr_fecs_method_push_r(),
|
||||
gr_fecs_method_push_adr_f(op.method.addr));
|
||||
|
||||
ret = gr_gk20a_ctx_wait_ucode(g, op.mailbox.id, op.mailbox.ret,
|
||||
op.cond.ok, op.mailbox.ok,
|
||||
op.cond.fail, op.mailbox.fail,
|
||||
false);
|
||||
if (ret != 0) {
|
||||
nvgpu_err(g,"fecs method: data=0x%08x push adr=0x%08x",
|
||||
op.method.data, op.method.addr);
|
||||
}
|
||||
|
||||
nvgpu_mutex_release(&gr->fecs_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int gr_gk20a_ctrl_ctxsw(struct gk20a *g, u32 fecs_method, u32 *ret)
|
||||
{
|
||||
return gr_gk20a_submit_fecs_method_op(g,
|
||||
return g->ops.gr.falcon.submit_fecs_method_op(g,
|
||||
(struct fecs_method_op_gk20a) {
|
||||
.method.addr = fecs_method,
|
||||
.method.data = ~U32(0U),
|
||||
@@ -470,7 +268,7 @@ ctxsw_already_enabled:
|
||||
|
||||
int gr_gk20a_halt_pipe(struct gk20a *g)
|
||||
{
|
||||
return gr_gk20a_submit_fecs_method_op(g,
|
||||
return g->ops.gr.falcon.submit_fecs_method_op(g,
|
||||
(struct fecs_method_op_gk20a) {
|
||||
.method.addr =
|
||||
gr_fecs_method_push_adr_halt_pipeline_v(),
|
||||
@@ -528,7 +326,7 @@ int gr_gk20a_fecs_ctx_bind_channel(struct gk20a *g,
|
||||
nvgpu_log_info(g, "bind channel %d inst ptr 0x%08x",
|
||||
c->chid, inst_base_ptr);
|
||||
|
||||
ret = gr_gk20a_submit_fecs_method_op(g,
|
||||
ret = g->ops.gr.falcon.submit_fecs_method_op(g,
|
||||
(struct fecs_method_op_gk20a) {
|
||||
.method.addr = gr_fecs_method_push_adr_bind_pointer_v(),
|
||||
.method.data = data,
|
||||
@@ -610,7 +408,7 @@ int gr_gk20a_fecs_ctx_image_save(struct channel_gk20a *c, u32 save_type)
|
||||
|
||||
nvgpu_log_fn(g, " ");
|
||||
|
||||
ret = gr_gk20a_submit_fecs_method_op(g,
|
||||
ret = g->ops.gr.falcon.submit_fecs_method_op(g,
|
||||
(struct fecs_method_op_gk20a) {
|
||||
.method.addr = save_type,
|
||||
.method.data = fecs_current_ctx_data(g, &c->inst_block),
|
||||
@@ -931,36 +729,6 @@ int gr_gk20a_update_hwpm_ctxsw_mode(struct gk20a *g,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int gr_gk20a_wait_ctxsw_ready(struct gk20a *g)
|
||||
{
|
||||
int ret;
|
||||
|
||||
nvgpu_log_fn(g, " ");
|
||||
|
||||
ret = gr_gk20a_ctx_wait_ucode(g, 0, NULL,
|
||||
GR_IS_UCODE_OP_EQUAL,
|
||||
eUcodeHandshakeInitComplete,
|
||||
GR_IS_UCODE_OP_SKIP, 0, false);
|
||||
if (ret != 0) {
|
||||
nvgpu_err(g, "falcon ucode init timeout");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (nvgpu_is_enabled(g, NVGPU_GR_USE_DMA_FOR_FW_BOOTSTRAP) ||
|
||||
nvgpu_is_enabled(g, NVGPU_SEC_SECUREGPCCS)) {
|
||||
gk20a_writel(g, gr_fecs_current_ctx_r(),
|
||||
gr_fecs_current_ctx_valid_false_f());
|
||||
}
|
||||
|
||||
gk20a_writel(g, gr_fecs_ctxsw_mailbox_clear_r(0), 0xffffffffU);
|
||||
gk20a_writel(g, gr_fecs_method_data_r(), 0x7fffffff);
|
||||
gk20a_writel(g, gr_fecs_method_push_r(),
|
||||
gr_fecs_method_push_adr_set_watchdog_timeout_f());
|
||||
|
||||
nvgpu_log_fn(g, "done");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gr_gk20a_init_ctx_state(struct gk20a *g)
|
||||
{
|
||||
int ret;
|
||||
@@ -978,7 +746,7 @@ int gr_gk20a_init_ctx_state(struct gk20a *g)
|
||||
op.method.addr =
|
||||
gr_fecs_method_push_adr_discover_image_size_v();
|
||||
op.mailbox.ret = &g->gr.ctx_vars.golden_image_size;
|
||||
ret = gr_gk20a_submit_fecs_method_op(g, op, false);
|
||||
ret = g->ops.gr.falcon.submit_fecs_method_op(g, op, false);
|
||||
if (ret != 0) {
|
||||
nvgpu_err(g,
|
||||
"query golden image size failed");
|
||||
@@ -988,7 +756,7 @@ int gr_gk20a_init_ctx_state(struct gk20a *g)
|
||||
op.method.addr =
|
||||
gr_fecs_method_push_adr_discover_pm_image_size_v();
|
||||
op.mailbox.ret = &g->gr.ctx_vars.pm_ctxsw_image_size;
|
||||
ret = gr_gk20a_submit_fecs_method_op(g, op, false);
|
||||
ret = g->ops.gr.falcon.submit_fecs_method_op(g, op, false);
|
||||
if (ret != 0) {
|
||||
nvgpu_err(g,
|
||||
"query pm ctx image size failed");
|
||||
@@ -1484,7 +1252,7 @@ static int gr_gk20a_init_ctxsw(struct gk20a *g)
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = gr_gk20a_wait_ctxsw_ready(g);
|
||||
err = g->ops.gr.falcon.wait_ctxsw_ready(g);
|
||||
if (err != 0) {
|
||||
goto out;
|
||||
}
|
||||
@@ -3040,7 +2808,7 @@ u32 gk20a_gr_nonstall_isr(struct gk20a *g)
|
||||
int gr_gk20a_fecs_get_reglist_img_size(struct gk20a *g, u32 *size)
|
||||
{
|
||||
BUG_ON(size == NULL);
|
||||
return gr_gk20a_submit_fecs_method_op(g,
|
||||
return g->ops.gr.falcon.submit_fecs_method_op(g,
|
||||
(struct fecs_method_op_gk20a) {
|
||||
.mailbox.id = 0U,
|
||||
.mailbox.data = 0U,
|
||||
@@ -3059,7 +2827,7 @@ int gr_gk20a_fecs_set_reglist_bind_inst(struct gk20a *g,
|
||||
{
|
||||
u32 data = fecs_current_ctx_data(g, inst_block);
|
||||
|
||||
return gr_gk20a_submit_fecs_method_op(g,
|
||||
return g->ops.gr.falcon.submit_fecs_method_op(g,
|
||||
(struct fecs_method_op_gk20a){
|
||||
.mailbox.id = 4U,
|
||||
.mailbox.data = data,
|
||||
@@ -3075,7 +2843,7 @@ int gr_gk20a_fecs_set_reglist_bind_inst(struct gk20a *g,
|
||||
|
||||
int gr_gk20a_fecs_set_reglist_virtual_addr(struct gk20a *g, u64 pmu_va)
|
||||
{
|
||||
return gr_gk20a_submit_fecs_method_op(g,
|
||||
return g->ops.gr.falcon.submit_fecs_method_op(g,
|
||||
(struct fecs_method_op_gk20a) {
|
||||
.mailbox.id = 4U,
|
||||
.mailbox.data = u64_lo32(pmu_va >> 8),
|
||||
|
||||
@@ -359,11 +359,6 @@ int gr_gk20a_handle_sm_exception(struct gk20a *g, u32 gpc, u32 tpc, u32 sm,
|
||||
bool *post_event, struct channel_gk20a *fault_ch,
|
||||
u32 *hww_global_esr);
|
||||
int gr_gk20a_init_ctx_state(struct gk20a *g);
|
||||
int gr_gk20a_submit_fecs_method_op(struct gk20a *g,
|
||||
struct fecs_method_op_gk20a op,
|
||||
bool sleepduringwait);
|
||||
int gr_gk20a_submit_fecs_sideband_method_op(struct gk20a *g,
|
||||
struct fecs_method_op_gk20a op);
|
||||
void gr_gk20a_free_gr_ctx(struct gk20a *g,
|
||||
struct vm_gk20a *vm, struct nvgpu_gr_ctx *gr_ctx);
|
||||
int gr_gk20a_halt_pipe(struct gk20a *g);
|
||||
@@ -398,10 +393,6 @@ int gk20a_gr_lock_down_sm(struct gk20a *g,
|
||||
bool check_errors);
|
||||
int gk20a_gr_wait_for_sm_lock_down(struct gk20a *g, u32 gpc, u32 tpc, u32 sm,
|
||||
u32 global_esr_mask, bool check_errors);
|
||||
int gr_gk20a_ctx_wait_ucode(struct gk20a *g, u32 mailbox_id,
|
||||
u32 *mailbox_ret, u32 opc_success,
|
||||
u32 mailbox_ok, u32 opc_fail,
|
||||
u32 mailbox_fail, bool sleepduringwait);
|
||||
|
||||
u32 gk20a_gr_get_sm_hww_warp_esr(struct gk20a *g, u32 gpc, u32 tpc, u32 sm);
|
||||
u32 gk20a_gr_get_sm_hww_global_esr(struct gk20a *g, u32 gpc, u32 tpc, u32 sm);
|
||||
|
||||
@@ -510,6 +510,11 @@ static const struct gpu_ops gm20b_ops = {
|
||||
nvgpu_gr_falcon_load_ctxsw_ucode,
|
||||
.wait_mem_scrubbing =
|
||||
gm20b_gr_falcon_wait_mem_scrubbing,
|
||||
.wait_ctxsw_ready = gm20b_gr_falcon_wait_ctxsw_ready,
|
||||
.submit_fecs_method_op =
|
||||
gm20b_gr_falcon_submit_fecs_method_op,
|
||||
.submit_fecs_sideband_method_op =
|
||||
gm20b_gr_falcon_submit_fecs_sideband_method_op,
|
||||
},
|
||||
},
|
||||
.fb = {
|
||||
|
||||
@@ -530,7 +530,7 @@ int gr_gp10b_init_ctx_state(struct gk20a *g)
|
||||
op.method.addr =
|
||||
gr_fecs_method_push_adr_discover_preemption_image_size_v();
|
||||
op.mailbox.ret = &g->gr.ctx_vars.preempt_image_size;
|
||||
err = gr_gk20a_submit_fecs_method_op(g, op, false);
|
||||
err = g->ops.gr.falcon.submit_fecs_method_op(g, op, false);
|
||||
if (err != 0) {
|
||||
nvgpu_err(g, "query preempt image size failed");
|
||||
return err;
|
||||
@@ -961,7 +961,7 @@ int gr_gp10b_set_cilp_preempt_pending(struct gk20a *g,
|
||||
"CILP: ctx id is 0x%x", gr_ctx->ctx_id);
|
||||
|
||||
/* send ucode method to set ctxsw interrupt */
|
||||
ret = gr_gk20a_submit_fecs_sideband_method_op(g,
|
||||
ret = g->ops.gr.falcon.submit_fecs_sideband_method_op(g,
|
||||
(struct fecs_method_op_gk20a) {
|
||||
.method.data = nvgpu_gr_ctx_get_ctx_id(g, gr_ctx),
|
||||
.method.addr =
|
||||
|
||||
@@ -595,6 +595,11 @@ static const struct gpu_ops gp10b_ops = {
|
||||
nvgpu_gr_falcon_load_ctxsw_ucode,
|
||||
.wait_mem_scrubbing =
|
||||
gm20b_gr_falcon_wait_mem_scrubbing,
|
||||
.wait_ctxsw_ready = gm20b_gr_falcon_wait_ctxsw_ready,
|
||||
.submit_fecs_method_op =
|
||||
gm20b_gr_falcon_submit_fecs_method_op,
|
||||
.submit_fecs_sideband_method_op =
|
||||
gm20b_gr_falcon_submit_fecs_sideband_method_op,
|
||||
},
|
||||
},
|
||||
.fb = {
|
||||
|
||||
@@ -740,6 +740,11 @@ static const struct gpu_ops gv100_ops = {
|
||||
nvgpu_gr_falcon_load_secure_ctxsw_ucode,
|
||||
.wait_mem_scrubbing =
|
||||
gm20b_gr_falcon_wait_mem_scrubbing,
|
||||
.wait_ctxsw_ready = gm20b_gr_falcon_wait_ctxsw_ready,
|
||||
.submit_fecs_method_op =
|
||||
gm20b_gr_falcon_submit_fecs_method_op,
|
||||
.submit_fecs_sideband_method_op =
|
||||
gm20b_gr_falcon_submit_fecs_sideband_method_op,
|
||||
},
|
||||
},
|
||||
.fb = {
|
||||
|
||||
@@ -699,6 +699,11 @@ static const struct gpu_ops gv11b_ops = {
|
||||
nvgpu_gr_falcon_load_ctxsw_ucode,
|
||||
.wait_mem_scrubbing =
|
||||
gm20b_gr_falcon_wait_mem_scrubbing,
|
||||
.wait_ctxsw_ready = gm20b_gr_falcon_wait_ctxsw_ready,
|
||||
.submit_fecs_method_op =
|
||||
gm20b_gr_falcon_submit_fecs_method_op,
|
||||
.submit_fecs_sideband_method_op =
|
||||
gm20b_gr_falcon_submit_fecs_sideband_method_op,
|
||||
},
|
||||
},
|
||||
.fb = {
|
||||
|
||||
@@ -466,6 +466,171 @@ int gm20b_gr_falcon_wait_mem_scrubbing(struct gk20a *g)
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int gm20b_gr_falcon_ctx_wait_ucode(struct gk20a *g, u32 mailbox_id,
|
||||
u32 *mailbox_ret, u32 opc_success,
|
||||
u32 mailbox_ok, u32 opc_fail,
|
||||
u32 mailbox_fail, bool sleepduringwait)
|
||||
{
|
||||
struct nvgpu_timeout timeout;
|
||||
u32 delay = GR_FECS_POLL_INTERVAL;
|
||||
enum wait_ucode_status check = WAIT_UCODE_LOOP;
|
||||
u32 reg;
|
||||
int err;
|
||||
|
||||
nvgpu_log_fn(g, " ");
|
||||
|
||||
if (sleepduringwait) {
|
||||
delay = POLL_DELAY_MIN_US;
|
||||
}
|
||||
|
||||
err = nvgpu_timeout_init(g, &timeout, nvgpu_get_poll_timeout(g),
|
||||
NVGPU_TIMER_CPU_TIMER);
|
||||
if (err != 0) {
|
||||
nvgpu_err(g, "ctxsw wait ucode timeout_init failed: %d", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
while (check == WAIT_UCODE_LOOP) {
|
||||
if (nvgpu_timeout_expired(&timeout) != 0) {
|
||||
check = WAIT_UCODE_TIMEOUT;
|
||||
}
|
||||
|
||||
reg = nvgpu_readl(g, gr_fecs_ctxsw_mailbox_r(mailbox_id));
|
||||
|
||||
if (mailbox_ret != NULL) {
|
||||
*mailbox_ret = reg;
|
||||
}
|
||||
|
||||
switch (opc_success) {
|
||||
case GR_IS_UCODE_OP_EQUAL:
|
||||
if (reg == mailbox_ok) {
|
||||
check = WAIT_UCODE_OK;
|
||||
}
|
||||
break;
|
||||
case GR_IS_UCODE_OP_NOT_EQUAL:
|
||||
if (reg != mailbox_ok) {
|
||||
check = WAIT_UCODE_OK;
|
||||
}
|
||||
break;
|
||||
case GR_IS_UCODE_OP_AND:
|
||||
if ((reg & mailbox_ok) != 0U) {
|
||||
check = WAIT_UCODE_OK;
|
||||
}
|
||||
break;
|
||||
case GR_IS_UCODE_OP_LESSER:
|
||||
if (reg < mailbox_ok) {
|
||||
check = WAIT_UCODE_OK;
|
||||
}
|
||||
break;
|
||||
case GR_IS_UCODE_OP_LESSER_EQUAL:
|
||||
if (reg <= mailbox_ok) {
|
||||
check = WAIT_UCODE_OK;
|
||||
}
|
||||
break;
|
||||
case GR_IS_UCODE_OP_SKIP:
|
||||
/* do no success check */
|
||||
break;
|
||||
default:
|
||||
nvgpu_err(g,
|
||||
"invalid success opcode 0x%x", opc_success);
|
||||
|
||||
check = WAIT_UCODE_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (opc_fail) {
|
||||
case GR_IS_UCODE_OP_EQUAL:
|
||||
if (reg == mailbox_fail) {
|
||||
check = WAIT_UCODE_ERROR;
|
||||
}
|
||||
break;
|
||||
case GR_IS_UCODE_OP_NOT_EQUAL:
|
||||
if (reg != mailbox_fail) {
|
||||
check = WAIT_UCODE_ERROR;
|
||||
}
|
||||
break;
|
||||
case GR_IS_UCODE_OP_AND:
|
||||
if ((reg & mailbox_fail) != 0U) {
|
||||
check = WAIT_UCODE_ERROR;
|
||||
}
|
||||
break;
|
||||
case GR_IS_UCODE_OP_LESSER:
|
||||
if (reg < mailbox_fail) {
|
||||
check = WAIT_UCODE_ERROR;
|
||||
}
|
||||
break;
|
||||
case GR_IS_UCODE_OP_LESSER_EQUAL:
|
||||
if (reg <= mailbox_fail) {
|
||||
check = WAIT_UCODE_ERROR;
|
||||
}
|
||||
break;
|
||||
case GR_IS_UCODE_OP_SKIP:
|
||||
/* do no check on fail*/
|
||||
break;
|
||||
default:
|
||||
nvgpu_err(g,
|
||||
"invalid fail opcode 0x%x", opc_fail);
|
||||
check = WAIT_UCODE_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
if (sleepduringwait) {
|
||||
nvgpu_usleep_range(delay, delay * 2U);
|
||||
delay = min_t(u32, delay << 1, POLL_DELAY_MAX_US);
|
||||
} else {
|
||||
nvgpu_udelay(delay);
|
||||
}
|
||||
}
|
||||
|
||||
if (check == WAIT_UCODE_TIMEOUT) {
|
||||
nvgpu_err(g,
|
||||
"timeout waiting on mailbox=%d value=0x%08x",
|
||||
mailbox_id, reg);
|
||||
g->ops.gr.falcon.dump_stats(g);
|
||||
gk20a_gr_debug_dump(g);
|
||||
return -1;
|
||||
} else if (check == WAIT_UCODE_ERROR) {
|
||||
nvgpu_err(g,
|
||||
"ucode method failed on mailbox=%d value=0x%08x",
|
||||
mailbox_id, reg);
|
||||
g->ops.gr.falcon.dump_stats(g);
|
||||
return -1;
|
||||
}
|
||||
|
||||
nvgpu_log_fn(g, "done");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gm20b_gr_falcon_wait_ctxsw_ready(struct gk20a *g)
|
||||
{
|
||||
int ret;
|
||||
|
||||
nvgpu_log_fn(g, " ");
|
||||
|
||||
ret = gm20b_gr_falcon_ctx_wait_ucode(g, 0, NULL,
|
||||
GR_IS_UCODE_OP_EQUAL,
|
||||
eUcodeHandshakeInitComplete,
|
||||
GR_IS_UCODE_OP_SKIP, 0, false);
|
||||
if (ret != 0) {
|
||||
nvgpu_err(g, "falcon ucode init timeout");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (nvgpu_is_enabled(g, NVGPU_GR_USE_DMA_FOR_FW_BOOTSTRAP) ||
|
||||
nvgpu_is_enabled(g, NVGPU_SEC_SECUREGPCCS)) {
|
||||
nvgpu_writel(g, gr_fecs_current_ctx_r(),
|
||||
gr_fecs_current_ctx_valid_false_f());
|
||||
}
|
||||
|
||||
nvgpu_writel(g, gr_fecs_ctxsw_mailbox_clear_r(0), 0xffffffffU);
|
||||
nvgpu_writel(g, gr_fecs_method_data_r(), 0x7fffffff);
|
||||
nvgpu_writel(g, gr_fecs_method_push_r(),
|
||||
gr_fecs_method_push_adr_set_watchdog_timeout_f());
|
||||
|
||||
nvgpu_log_fn(g, "done");
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 gm20b_gr_falcon_fecs_base_addr(void)
|
||||
{
|
||||
return gr_fecs_irqsset_r();
|
||||
@@ -504,3 +669,77 @@ void gm20b_gr_falcon_set_current_ctx_invalid(struct gk20a *g)
|
||||
gr_fecs_current_ctx_valid_false_f());
|
||||
}
|
||||
|
||||
/* The following is a less brittle way to call gr_gk20a_submit_fecs_method(...)
|
||||
* We should replace most, if not all, fecs method calls to this instead.
|
||||
*/
|
||||
int gm20b_gr_falcon_submit_fecs_method_op(struct gk20a *g,
|
||||
struct fecs_method_op_gk20a op,
|
||||
bool sleepduringwait)
|
||||
{
|
||||
struct gr_gk20a *gr = &g->gr;
|
||||
int ret;
|
||||
|
||||
nvgpu_mutex_acquire(&gr->fecs_mutex);
|
||||
|
||||
if (op.mailbox.id != 0U) {
|
||||
nvgpu_writel(g, gr_fecs_ctxsw_mailbox_r(op.mailbox.id),
|
||||
op.mailbox.data);
|
||||
}
|
||||
|
||||
nvgpu_writel(g, gr_fecs_ctxsw_mailbox_clear_r(0),
|
||||
gr_fecs_ctxsw_mailbox_clear_value_f(op.mailbox.clr));
|
||||
|
||||
nvgpu_writel(g, gr_fecs_method_data_r(), op.method.data);
|
||||
nvgpu_writel(g, gr_fecs_method_push_r(),
|
||||
gr_fecs_method_push_adr_f(op.method.addr));
|
||||
|
||||
/* op.mailbox.id == 4 cases require waiting for completion on
|
||||
* for op.mailbox.id == 0
|
||||
*/
|
||||
if (op.mailbox.id == 4U) {
|
||||
op.mailbox.id = 0;
|
||||
}
|
||||
|
||||
ret = gm20b_gr_falcon_ctx_wait_ucode(g, op.mailbox.id, op.mailbox.ret,
|
||||
op.cond.ok, op.mailbox.ok,
|
||||
op.cond.fail, op.mailbox.fail,
|
||||
sleepduringwait);
|
||||
if (ret != 0) {
|
||||
nvgpu_err(g, "fecs method: data=0x%08x push adr=0x%08x",
|
||||
op.method.data, op.method.addr);
|
||||
}
|
||||
|
||||
nvgpu_mutex_release(&gr->fecs_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Sideband mailbox writes are done a bit differently */
|
||||
int gm20b_gr_falcon_submit_fecs_sideband_method_op(struct gk20a *g,
|
||||
struct fecs_method_op_gk20a op)
|
||||
{
|
||||
struct gr_gk20a *gr = &g->gr;
|
||||
int ret;
|
||||
|
||||
nvgpu_mutex_acquire(&gr->fecs_mutex);
|
||||
|
||||
nvgpu_writel(g, gr_fecs_ctxsw_mailbox_clear_r(op.mailbox.id),
|
||||
gr_fecs_ctxsw_mailbox_clear_value_f(op.mailbox.clr));
|
||||
|
||||
nvgpu_writel(g, gr_fecs_method_data_r(), op.method.data);
|
||||
nvgpu_writel(g, gr_fecs_method_push_r(),
|
||||
gr_fecs_method_push_adr_f(op.method.addr));
|
||||
|
||||
ret = gm20b_gr_falcon_ctx_wait_ucode(g, op.mailbox.id, op.mailbox.ret,
|
||||
op.cond.ok, op.mailbox.ok,
|
||||
op.cond.fail, op.mailbox.fail,
|
||||
false);
|
||||
if (ret != 0) {
|
||||
nvgpu_err(g, "fecs method: data=0x%08x push adr=0x%08x",
|
||||
op.method.data, op.method.addr);
|
||||
}
|
||||
|
||||
nvgpu_mutex_release(&gr->fecs_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
|
||||
struct gk20a;
|
||||
|
||||
struct fecs_method_op_gk20a;
|
||||
|
||||
u32 gm20b_gr_falcon_fecs_base_addr(void);
|
||||
u32 gm20b_gr_falcon_gpccs_base_addr(void);
|
||||
void gm20b_gr_falcon_fecs_dump_stats(struct gk20a *g);
|
||||
@@ -54,6 +56,11 @@ void gm20b_gr_falcon_load_ctxsw_ucode_boot(struct gk20a *g,
|
||||
u32 reg_offset, u32 boot_entry, u32 addr_load32, u32 blocks,
|
||||
u32 dst);
|
||||
int gm20b_gr_falcon_wait_mem_scrubbing(struct gk20a *g);
|
||||
int gm20b_gr_falcon_wait_ctxsw_ready(struct gk20a *g);
|
||||
int gm20b_gr_falcon_submit_fecs_method_op(struct gk20a *g,
|
||||
struct fecs_method_op_gk20a op, bool sleepduringwait);
|
||||
int gm20b_gr_falcon_submit_fecs_sideband_method_op(struct gk20a *g,
|
||||
struct fecs_method_op_gk20a op);
|
||||
|
||||
void gm20b_gr_falcon_set_current_ctx_invalid(struct gk20a *g);
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ int gp10b_fecs_trace_flush(struct gk20a *g)
|
||||
nvgpu_log(g, gpu_dbg_fn|gpu_dbg_ctxsw, " ");
|
||||
|
||||
err = nvgpu_pg_elpg_protected_call(g,
|
||||
gr_gk20a_submit_fecs_method_op(g, op, false));
|
||||
g->ops.gr.falcon.submit_fecs_method_op(g, op, false));
|
||||
if (err != 0)
|
||||
nvgpu_err(g, "write timestamp record failed");
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ static int gm20b_gr_init_zcull_ctxsw_image_size(struct gk20a *g,
|
||||
gr_fecs_method_push_adr_discover_zcull_image_size_v();
|
||||
|
||||
op.mailbox.ret = &gr_zcull->zcull_ctxsw_image_size;
|
||||
ret = gr_gk20a_submit_fecs_method_op(g, op, false);
|
||||
ret = g->ops.gr.falcon.submit_fecs_method_op(g, op, false);
|
||||
if (ret != 0) {
|
||||
nvgpu_err(g,
|
||||
"query zcull ctx image size failed");
|
||||
|
||||
@@ -586,6 +586,12 @@ struct gpu_ops {
|
||||
u32 addr_load32, u32 blocks, u32 dst);
|
||||
int (*load_ctxsw_ucode)(struct gk20a *g);
|
||||
int (*wait_mem_scrubbing)(struct gk20a *g);
|
||||
int (*wait_ctxsw_ready)(struct gk20a *g);
|
||||
int (*submit_fecs_method_op)(struct gk20a *g,
|
||||
struct fecs_method_op_gk20a op,
|
||||
bool sleepduringwait);
|
||||
int (*submit_fecs_sideband_method_op)(struct gk20a *g,
|
||||
struct fecs_method_op_gk20a op);
|
||||
} falcon;
|
||||
|
||||
#ifdef CONFIG_GK20A_CTXSW_TRACE
|
||||
|
||||
@@ -773,6 +773,11 @@ static const struct gpu_ops tu104_ops = {
|
||||
nvgpu_gr_falcon_load_secure_ctxsw_ucode,
|
||||
.wait_mem_scrubbing =
|
||||
gm20b_gr_falcon_wait_mem_scrubbing,
|
||||
.wait_ctxsw_ready = gm20b_gr_falcon_wait_ctxsw_ready,
|
||||
.submit_fecs_method_op =
|
||||
gm20b_gr_falcon_submit_fecs_method_op,
|
||||
.submit_fecs_sideband_method_op =
|
||||
gm20b_gr_falcon_submit_fecs_sideband_method_op,
|
||||
},
|
||||
},
|
||||
.fb = {
|
||||
|
||||
Reference in New Issue
Block a user