diff --git a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c index 2eef936ab..58c11a305 100644 --- a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c @@ -75,6 +75,7 @@ #define CTXSW_MEM_SCRUBBING_TIMEOUT_DEFAULT 10 #define FECS_ARB_CMD_TIMEOUT_MAX 40 #define FECS_ARB_CMD_TIMEOUT_DEFAULT 2 +#define GFXP_WFI_TIMEOUT_COUNT_DEFAULT 100000 static int gk20a_init_gr_bind_fecs_elpg(struct gk20a *g); @@ -5174,6 +5175,8 @@ static int gk20a_init_gr_setup_sw(struct gk20a *g) gr_gk20a_load_zbc_default_table(g, gr); + gr->gfxp_wfi_timeout_count = GFXP_WFI_TIMEOUT_COUNT_DEFAULT; + nvgpu_mutex_init(&gr->ctx_mutex); nvgpu_spinlock_init(&gr->ch_tlb_lock); diff --git a/drivers/gpu/nvgpu/gk20a/gr_gk20a.h b/drivers/gpu/nvgpu/gk20a/gr_gk20a.h index 7a9ad5c1f..1cbc50d4a 100644 --- a/drivers/gpu/nvgpu/gk20a/gr_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gr_gk20a.h @@ -322,6 +322,7 @@ struct gr_gk20a { u32 timeslice_mode; u32 czf_bypass; u32 pd_max_batches; + u32 gfxp_wfi_timeout_count; struct gr_ctx_buffer_desc global_ctx_buffer[NR_GLOBAL_CTX_BUF]; diff --git a/drivers/gpu/nvgpu/gp10b/gp10b_sysfs.c b/drivers/gpu/nvgpu/gp10b/gp10b_sysfs.c index adfb4bafb..571e397d8 100644 --- a/drivers/gpu/nvgpu/gp10b/gp10b_sysfs.c +++ b/drivers/gpu/nvgpu/gp10b/gp10b_sysfs.c @@ -106,6 +106,56 @@ static ssize_t pd_max_batches_read(struct device *dev, static DEVICE_ATTR(pd_max_batches, ROOTRW, pd_max_batches_read, pd_max_batches_store); +static int write_gfxp_wfi_timeout_count(struct gk20a *g, u32 val) +{ + gk20a_writel(g, gr_fe_gfxp_wfi_timeout_r(), + gr_fe_gfxp_wfi_timeout_count_f(val)); + + return 0; +} + +static ssize_t gfxp_wfi_timeout_count_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct gk20a *g = get_gk20a(dev); + struct gr_gk20a *gr = &g->gr; + unsigned long val = 0; + int err = -1; + + if (kstrtoul(buf, 10, &val) < 0) + return -EINVAL; + + if (val >= 100*1000*1000) /* 100ms @ 1Ghz */ + return -EINVAL; + + gr->gfxp_wfi_timeout_count = val; + + if (!g->power_on) + return count; + + err = gk20a_busy(g); + if (err) + return err; + gr_gk20a_elpg_protected_call(g, + write_gfxp_wfi_timeout_count(g, val)); + gk20a_idle(g); + + return count; +} + +static ssize_t gfxp_wfi_timeout_count_read(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gk20a *g = get_gk20a(dev); + struct gr_gk20a *gr = &g->gr; + u32 val = gr->gfxp_wfi_timeout_count; + + return snprintf(buf, PAGE_SIZE, "%d\n", val); +} + +static DEVICE_ATTR(gfxp_wfi_timeout_count, ROOTRW, + gfxp_wfi_timeout_count_read, gfxp_wfi_timeout_count_store); + void gp10b_create_sysfs(struct device *dev) { struct gk20a *g = get_gk20a(dev); @@ -116,6 +166,7 @@ void gp10b_create_sysfs(struct device *dev) error |= device_create_file(dev, &dev_attr_ecc_enable); error |= device_create_file(dev, &dev_attr_czf_bypass); error |= device_create_file(dev, &dev_attr_pd_max_batches); + error |= device_create_file(dev, &dev_attr_gfxp_wfi_timeout_count); if (error) dev_err(dev, "Failed to create sysfs attributes!\n"); } @@ -125,4 +176,5 @@ void gp10b_remove_sysfs(struct device *dev) device_remove_file(dev, &dev_attr_ecc_enable); device_remove_file(dev, &dev_attr_czf_bypass); device_remove_file(dev, &dev_attr_pd_max_batches); + device_remove_file(dev, &dev_attr_gfxp_wfi_timeout_count); } diff --git a/drivers/gpu/nvgpu/gp10b/gr_gp10b.c b/drivers/gpu/nvgpu/gp10b/gr_gp10b.c index befaf2981..db4fcdc62 100644 --- a/drivers/gpu/nvgpu/gp10b/gr_gp10b.c +++ b/drivers/gpu/nvgpu/gp10b/gr_gp10b.c @@ -38,8 +38,6 @@ #include #include -#define NVGPU_GFXP_WFI_TIMEOUT_US 100LL - static bool gr_gp10b_is_valid_class(struct gk20a *g, u32 class_num) { bool valid = false; @@ -2295,13 +2293,9 @@ static int gp10b_gr_fuse_override(struct gk20a *g) static int gr_gp10b_init_preemption_state(struct gk20a *g) { - struct gk20a_platform *platform = gk20a_get_platform(g->dev); u32 debug_2; - u64 sysclk_rate; - u32 sysclk_cycles; - - sysclk_rate = platform->clk_get_rate(g->dev); - sysclk_cycles = (u32)((sysclk_rate * NVGPU_GFXP_WFI_TIMEOUT_US) / 1000000ULL); + struct gr_gk20a *gr = &g->gr; + u32 sysclk_cycles = gr->gfxp_wfi_timeout_count; gk20a_writel(g, gr_fe_gfxp_wfi_timeout_r(), gr_fe_gfxp_wfi_timeout_count_f(sysclk_cycles));