diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c index 4283e1adb..c07e7e4b7 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a.c @@ -2142,6 +2142,17 @@ int gk20a_init_gpu_characteristics(struct gk20a *g) if (platform->clk_round_rate) gpu->max_freq = platform->clk_round_rate(g->dev, UINT_MAX); + g->ops.gr.get_preemption_mode_flags(g, &g->gr.preemption_mode_rec); + gpu->graphics_preemption_mode_flags = + g->gr.preemption_mode_rec.graphics_preemption_mode_flags; + gpu->compute_preemption_mode_flags = + g->gr.preemption_mode_rec.compute_preemption_mode_flags; + gpu->default_graphics_preempt_mode = + g->gr.preemption_mode_rec.default_graphics_preempt_mode; + gpu->default_compute_preempt_mode = + g->gr.preemption_mode_rec.default_compute_preempt_mode; + + return 0; } diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index 64e410dba..09198fa51 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h @@ -257,6 +257,8 @@ struct gpu_ops { int (*set_preemption_mode)(struct channel_gk20a *ch, u32 graphics_preempt_mode, u32 compute_preempt_mode); + int (*get_preemption_mode_flags)(struct gk20a *g, + struct nvgpu_preemption_modes_rec *preemption_modes_rec); } gr; const char *name; struct { diff --git a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c index aa63e5593..8b645cc2a 100644 --- a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c @@ -8659,6 +8659,22 @@ clean_up: return err; } +static int gr_gk20a_get_preemption_mode_flags(struct gk20a *g, + struct nvgpu_preemption_modes_rec *preemption_modes_rec) +{ + preemption_modes_rec->graphics_preemption_mode_flags = + NVGPU_GRAPHICS_PREEMPTION_MODE_WFI; + preemption_modes_rec->compute_preemption_mode_flags = + NVGPU_COMPUTE_PREEMPTION_MODE_WFI; + + preemption_modes_rec->default_graphics_preempt_mode = + NVGPU_GRAPHICS_PREEMPTION_MODE_WFI; + preemption_modes_rec->default_compute_preempt_mode = + NVGPU_COMPUTE_PREEMPTION_MODE_WFI; + + return 0; +} + void gk20a_init_gr_ops(struct gpu_ops *gops) { gops->gr.access_smpc_reg = gr_gk20a_access_smpc_reg; @@ -8726,4 +8742,5 @@ void gk20a_init_gr_ops(struct gpu_ops *gops) gops->gr.update_sm_error_state = gk20a_gr_update_sm_error_state; gops->gr.clear_sm_error_state = gk20a_gr_clear_sm_error_state; gops->gr.suspend_contexts = gr_gk20a_suspend_contexts; + gops->gr.get_preemption_mode_flags = gr_gk20a_get_preemption_mode_flags; } diff --git a/drivers/gpu/nvgpu/gk20a/gr_gk20a.h b/drivers/gpu/nvgpu/gk20a/gr_gk20a.h index 10997c17a..15d1ea7d0 100644 --- a/drivers/gpu/nvgpu/gk20a/gr_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gr_gk20a.h @@ -188,6 +188,14 @@ struct gr_gk20a_isr_data { u32 class_num; }; +struct nvgpu_preemption_modes_rec { + u32 graphics_preemption_mode_flags; /* supported preemption modes */ + u32 compute_preemption_mode_flags; /* supported preemption modes */ + + u32 default_graphics_preempt_mode; /* default mode */ + u32 default_compute_preempt_mode; /* default mode */ +}; + struct gr_gk20a { struct gk20a *g; struct { @@ -325,6 +333,7 @@ struct gr_gk20a { bool sw_ready; bool skip_ucode_init; + struct nvgpu_preemption_modes_rec preemption_mode_rec; #ifdef CONFIG_ARCH_TEGRA_18x_SOC struct gr_t18x t18x; #endif diff --git a/drivers/gpu/nvgpu/gm20b/gr_gm20b.c b/drivers/gpu/nvgpu/gm20b/gr_gm20b.c index dbe30f00f..2a982f871 100644 --- a/drivers/gpu/nvgpu/gm20b/gr_gm20b.c +++ b/drivers/gpu/nvgpu/gm20b/gr_gm20b.c @@ -1345,6 +1345,23 @@ fail: return err; } +static int gr_gm20b_get_preemption_mode_flags(struct gk20a *g, + struct nvgpu_preemption_modes_rec *preemption_modes_rec) +{ + preemption_modes_rec->graphics_preemption_mode_flags = + NVGPU_GRAPHICS_PREEMPTION_MODE_WFI; + preemption_modes_rec->compute_preemption_mode_flags = ( + NVGPU_COMPUTE_PREEMPTION_MODE_WFI | + NVGPU_COMPUTE_PREEMPTION_MODE_CTA); + + preemption_modes_rec->default_graphics_preempt_mode = + NVGPU_GRAPHICS_PREEMPTION_MODE_WFI; + preemption_modes_rec->default_compute_preempt_mode = + NVGPU_COMPUTE_PREEMPTION_MODE_CTA; + + return 0; +} + void gm20b_init_gr(struct gpu_ops *gops) { gops->gr.init_gpc_mmu = gr_gm20b_init_gpc_mmu; @@ -1417,4 +1434,5 @@ void gm20b_init_gr(struct gpu_ops *gops) gops->gr.update_sm_error_state = gm20b_gr_update_sm_error_state; gops->gr.clear_sm_error_state = gm20b_gr_clear_sm_error_state; gops->gr.suspend_contexts = gr_gk20a_suspend_contexts; + gops->gr.get_preemption_mode_flags = gr_gm20b_get_preemption_mode_flags; } diff --git a/include/uapi/linux/nvgpu.h b/include/uapi/linux/nvgpu.h index 8ebe8d064..82b78f8f9 100644 --- a/include/uapi/linux/nvgpu.h +++ b/include/uapi/linux/nvgpu.h @@ -187,6 +187,13 @@ struct nvgpu_gpu_characteristics { __u64 max_freq; + /* supported preemption modes */ + __u32 graphics_preemption_mode_flags; /* NVGPU_GRAPHICS_PREEMPTION_MODE_* */ + __u32 compute_preemption_mode_flags; /* NVGPU_COMPUTE_PREEMPTION_MODE_* */ + /* default preemption modes */ + __u32 default_graphics_preempt_mode; /* NVGPU_GRAPHICS_PREEMPTION_MODE_* */ + __u32 default_compute_preempt_mode; /* NVGPU_COMPUTE_PREEMPTION_MODE_* */ + /* Notes: - This struct can be safely appended with new fields. However, always keep the structure size multiple of 8 and make sure that the binary