From 842bef712439c76bc8b1ed66d30e32f0b2930c47 Mon Sep 17 00:00:00 2001 From: Divya Singhatwaria Date: Tue, 16 Mar 2021 22:29:33 +0530 Subject: [PATCH] gpu: nvgpu: Support GPC and FBP Floorsweeping MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add gops_fbp_fs and gops_gpc_pg struct - Add HALs to write to NV_FUSE_CTRL_OPT_FBP and NV_FUSE_CTRL_OPT_GPC fuses needed for floorsweeping - Add set_fbp_mask and set_gpc_mask to probe FBP and GPC mask respectively during gpu probe - Add sysfs node: fbp_fs_mask and gpc_fs_mask to store FBP and GPC floorsweeping mask sent from userspace - Move the floorsweeping programming early in NVGPU’s GPU init function and then issue a PRI init. JIRA NVGPU-6433 Change-Id: I84764d625c69914c107e1e8c7f29c476c2f64f78 Signed-off-by: Divya Singhatwaria Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2499571 Reviewed-by: svc-mobile-coverity Reviewed-by: svc-mobile-misra Reviewed-by: svc-mobile-cert Reviewed-by: svc_kernel_abi Reviewed-by: Vijayakumar Subbu Reviewed-by: mobile promotions GVS: Gerrit_Virtual_Submit Tested-by: mobile promotions --- drivers/gpu/nvgpu/common/init/nvgpu_init.c | 59 ++++++-- drivers/gpu/nvgpu/hal/init/hal_gm20b.c | 16 +++ drivers/gpu/nvgpu/hal/init/hal_gp10b.c | 16 +++ drivers/gpu/nvgpu/hal/init/hal_gv11b.c | 16 +++ drivers/gpu/nvgpu/hal/init/hal_tu104.c | 3 + .../gpu/nvgpu/hal/vgpu/init/vgpu_hal_gv11b.c | 3 + drivers/gpu/nvgpu/include/nvgpu/gk20a.h | 21 +++ .../gpu/nvgpu/include/nvgpu/gops/floorsweep.h | 11 ++ drivers/gpu/nvgpu/include/nvgpu/gops/fuse.h | 23 +++ drivers/gpu/nvgpu/include/nvgpu/gpu_ops.h | 2 + drivers/gpu/nvgpu/os/linux/driver_common.c | 6 + drivers/gpu/nvgpu/os/linux/module.c | 15 ++ drivers/gpu/nvgpu/os/linux/platform_gk20a.h | 15 ++ drivers/gpu/nvgpu/os/linux/sysfs.c | 136 ++++++++++++++++++ 14 files changed, 334 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/nvgpu/common/init/nvgpu_init.c b/drivers/gpu/nvgpu/common/init/nvgpu_init.c index 862c0b383..e2a5f7d98 100644 --- a/drivers/gpu/nvgpu/common/init/nvgpu_init.c +++ b/drivers/gpu/nvgpu/common/init/nvgpu_init.c @@ -431,15 +431,47 @@ static int nvgpu_init_fbpa_ecc(struct gk20a *g) static int nvgpu_init_power_gate(struct gk20a *g) { int err; - u32 fuse_status; + u32 fuse_status = 0x0; /* - * Power gate the chip as per the TPC PG mask + * Floorsweep the FBP as per the FBP_FS mask + * and the fuse_status register. + * If FBP_FS mask is invalid, return error. + */ + + g->can_fbp_fs = false; + + if (g->ops.fbp_fs.init_fbp_floorsweep != NULL) { + err = g->ops.fbp_fs.init_fbp_floorsweep(g, &g->can_fbp_fs); + if (err != 0) { + return err; + } + } + + /* + * Floorsweep the GPC as per the GPC_FS mask + * and the fuse_status register. + * If GPC_FS mask is invalid halt the GPU poweron. + */ + + g->can_gpc_fs = false; + + if (g->ops.gpc_pg.init_gpc_powergate != NULL) { + err = g->ops.gpc_pg.init_gpc_powergate(g, &g->can_gpc_fs); + if (err != 0) { + return err; + } + } + + /* + * Powergate the chip as per the TPC PG mask * and the fuse_status register. * If TPC PG mask is invalid halt the GPU poweron. */ g->can_tpc_powergate = false; - fuse_status = g->ops.fuse.fuse_status_opt_tpc_gpc(g, 0); + if (g->ops.fuse.fuse_status_opt_tpc_gpc != NULL) { + fuse_status = g->ops.fuse.fuse_status_opt_tpc_gpc(g, 0); + } if (g->ops.tpc.init_tpc_powergate != NULL) { err = g->ops.tpc.init_tpc_powergate(g, fuse_status); @@ -453,6 +485,17 @@ static int nvgpu_init_power_gate(struct gk20a *g) static int nvgpu_init_power_gate_gr(struct gk20a *g) { + /* Floorsweep FBP */ + if (g->can_fbp_fs && (g->ops.fbp_fs.fbp_static_fs != NULL)) { + g->ops.fbp_fs.fbp_static_fs(g); + } + + /* Floorsweep GPC */ + if (g->can_gpc_fs && (g->ops.gpc_pg.gpc_static_pg != NULL)) { + g->ops.gpc_pg.gpc_static_pg(g); + } + + /* Floorsweep TPC */ if (g->can_tpc_powergate && (g->ops.tpc.tpc_gr_pg != NULL)) { g->ops.tpc.tpc_gr_pg(g); } @@ -632,6 +675,11 @@ static int nvgpu_early_init(struct gk20a *g) #endif NVGPU_INIT_TABLE_ENTRY(&nvgpu_init_interrupt_setup, NO_FLAG), NVGPU_INIT_TABLE_ENTRY(g->ops.bus.init_hw, NO_FLAG), +#ifdef CONFIG_NVGPU_STATIC_POWERGATE + NVGPU_INIT_TABLE_ENTRY(&nvgpu_init_power_gate, NO_FLAG), + NVGPU_INIT_TABLE_ENTRY(&nvgpu_init_acquire_static_pg_lock, NO_FLAG), + NVGPU_INIT_TABLE_ENTRY(&nvgpu_init_power_gate_gr, NO_FLAG), +#endif NVGPU_INIT_TABLE_ENTRY(g->ops.priv_ring.enable_priv_ring, NO_FLAG), #ifdef CONFIG_NVGPU_NON_FUSA @@ -793,11 +841,6 @@ int nvgpu_finalize_poweron(struct gk20a *g) NVGPU_INIT_TABLE_ENTRY(g->ops.fifo.fifo_init_support, NO_FLAG), NVGPU_INIT_TABLE_ENTRY(g->ops.therm.elcg_init_idle_filters, NO_FLAG), -#ifdef CONFIG_NVGPU_STATIC_POWERGATE - NVGPU_INIT_TABLE_ENTRY(&nvgpu_init_power_gate, NO_FLAG), - NVGPU_INIT_TABLE_ENTRY(&nvgpu_init_acquire_static_pg_lock, NO_FLAG), - NVGPU_INIT_TABLE_ENTRY(&nvgpu_init_power_gate_gr, NO_FLAG), -#endif NVGPU_INIT_TABLE_ENTRY(&nvgpu_netlist_init_ctx_vars, NO_FLAG), /* prepare portion of sw required for enable hw */ NVGPU_INIT_TABLE_ENTRY(&nvgpu_gr_alloc, NO_FLAG), diff --git a/drivers/gpu/nvgpu/hal/init/hal_gm20b.c b/drivers/gpu/nvgpu/hal/init/hal_gm20b.c index 53dcef2af..e4dd47d7d 100644 --- a/drivers/gpu/nvgpu/hal/init/hal_gm20b.c +++ b/drivers/gpu/nvgpu/hal/init/hal_gm20b.c @@ -1030,7 +1030,10 @@ static const struct gops_fuse gm20b_ops_fuse = { .fuse_status_opt_fbp = gm20b_fuse_status_opt_fbp, .fuse_status_opt_l2_fbp = gm20b_fuse_status_opt_l2_fbp, .fuse_status_opt_tpc_gpc = gm20b_fuse_status_opt_tpc_gpc, + .fuse_status_opt_gpc = NULL, .fuse_ctrl_opt_tpc_gpc = gm20b_fuse_ctrl_opt_tpc_gpc, + .fuse_ctrl_opt_fbp = NULL, + .fuse_ctrl_opt_gpc = NULL, .fuse_opt_sec_debug_en = gm20b_fuse_opt_sec_debug_en, .fuse_opt_priv_sec_en = gm20b_fuse_opt_priv_sec_en, .read_vin_cal_fuse_rev = NULL, @@ -1056,6 +1059,17 @@ static const struct gops_tpc gm20b_ops_tpc = { .init_tpc_powergate = NULL, .tpc_gr_pg = NULL, }; + +static const struct gops_fbp_fs gm20b_ops_fbp_fs = { + .init_fbp_floorsweep = NULL, + .fbp_static_fs = NULL, +}; + +static const struct gops_gpc_pg gm20b_ops_gpc_pg = { + .init_gpc_powergate = NULL, + .gpc_static_pg = NULL, +}; + #endif static const struct gops_grmgr gm20b_ops_grmgr = { @@ -1170,6 +1184,8 @@ int gm20b_init_hal(struct gk20a *g) gops->top = gm20b_ops_top; #ifdef CONFIG_NVGPU_STATIC_POWERGATE gops->tpc = gm20b_ops_tpc; + gops->fbp_fs = gm20b_ops_fbp_fs; + gops->gpc_pg = gm20b_ops_gpc_pg; #endif gops->grmgr = gm20b_ops_grmgr; gops->cic_mon = gm20b_ops_cic_mon; diff --git a/drivers/gpu/nvgpu/hal/init/hal_gp10b.c b/drivers/gpu/nvgpu/hal/init/hal_gp10b.c index 666b970dd..3be1f7190 100644 --- a/drivers/gpu/nvgpu/hal/init/hal_gp10b.c +++ b/drivers/gpu/nvgpu/hal/init/hal_gp10b.c @@ -1128,7 +1128,10 @@ static const struct gops_fuse gp10b_ops_fuse = { .fuse_status_opt_fbp = gm20b_fuse_status_opt_fbp, .fuse_status_opt_l2_fbp = gm20b_fuse_status_opt_l2_fbp, .fuse_status_opt_tpc_gpc = gm20b_fuse_status_opt_tpc_gpc, + .fuse_status_opt_gpc = NULL, .fuse_ctrl_opt_tpc_gpc = gm20b_fuse_ctrl_opt_tpc_gpc, + .fuse_ctrl_opt_fbp = NULL, + .fuse_ctrl_opt_gpc = NULL, .fuse_opt_sec_debug_en = gm20b_fuse_opt_sec_debug_en, .fuse_opt_priv_sec_en = gm20b_fuse_opt_priv_sec_en, .read_vin_cal_fuse_rev = NULL, @@ -1155,6 +1158,17 @@ static const struct gops_tpc gp10b_ops_tpc = { .init_tpc_powergate = NULL, .tpc_gr_pg = NULL, }; + +static const struct gops_fbp_fs gp10b_ops_fbp_fs = { + .init_fbp_floorsweep = NULL, + .fbp_static_fs = NULL, +}; + +static const struct gops_gpc_pg gp10b_ops_gpc_pg = { + .init_gpc_powergate = NULL, + .gpc_static_pg = NULL, +}; + #endif static const struct gops_grmgr gp10b_ops_grmgr = { @@ -1259,6 +1273,8 @@ int gp10b_init_hal(struct gk20a *g) gops->top = gp10b_ops_top; #ifdef CONFIG_NVGPU_STATIC_POWERGATE gops->tpc = gp10b_ops_tpc; + gops->fbp_fs = gp10b_ops_fbp_fs; + gops->gpc_pg = gp10b_ops_gpc_pg; #endif gops->grmgr = gp10b_ops_grmgr; gops->cic_mon = gp10b_ops_cic_mon; diff --git a/drivers/gpu/nvgpu/hal/init/hal_gv11b.c b/drivers/gpu/nvgpu/hal/init/hal_gv11b.c index a1789dcf1..e6433c198 100644 --- a/drivers/gpu/nvgpu/hal/init/hal_gv11b.c +++ b/drivers/gpu/nvgpu/hal/init/hal_gv11b.c @@ -1405,8 +1405,11 @@ static const struct gops_fuse gv11b_ops_fuse = { .fuse_status_opt_fbio = gm20b_fuse_status_opt_fbio, .fuse_status_opt_fbp = gm20b_fuse_status_opt_fbp, .fuse_status_opt_l2_fbp = gm20b_fuse_status_opt_l2_fbp, + .fuse_status_opt_gpc = NULL, .fuse_status_opt_tpc_gpc = gm20b_fuse_status_opt_tpc_gpc, .fuse_ctrl_opt_tpc_gpc = gm20b_fuse_ctrl_opt_tpc_gpc, + .fuse_ctrl_opt_fbp = NULL, + .fuse_ctrl_opt_gpc = NULL, .fuse_opt_sec_debug_en = gm20b_fuse_opt_sec_debug_en, .fuse_opt_priv_sec_en = gm20b_fuse_opt_priv_sec_en, .read_vin_cal_fuse_rev = NULL, @@ -1434,6 +1437,17 @@ static const struct gops_tpc gv11b_ops_tpc = { .init_tpc_powergate = gv11b_tpc_powergate, .tpc_gr_pg = gv11b_gr_pg_tpc, }; + +static const struct gops_fbp_fs gv11b_ops_fbp_fs = { + .init_fbp_floorsweep = NULL, + .fbp_static_fs = NULL, +}; + +static const struct gops_gpc_pg gv11b_ops_gpc_pg = { + .init_gpc_powergate = NULL, + .gpc_static_pg = NULL, +}; + #endif static const struct gops_grmgr gv11b_ops_grmgr = { @@ -1539,6 +1553,8 @@ int gv11b_init_hal(struct gk20a *g) gops->top = gv11b_ops_top; #ifdef CONFIG_NVGPU_STATIC_POWERGATE gops->tpc = gv11b_ops_tpc; + gops->fbp_fs = gv11b_ops_fbp_fs; + gops->gpc_pg = gv11b_ops_gpc_pg; #endif gops->grmgr = gv11b_ops_grmgr; gops->cic_mon = gv11b_ops_cic_mon; diff --git a/drivers/gpu/nvgpu/hal/init/hal_tu104.c b/drivers/gpu/nvgpu/hal/init/hal_tu104.c index 870bfc925..931ee2a74 100644 --- a/drivers/gpu/nvgpu/hal/init/hal_tu104.c +++ b/drivers/gpu/nvgpu/hal/init/hal_tu104.c @@ -1510,6 +1510,9 @@ static const struct gops_fuse tu104_ops_fuse = { .fuse_status_opt_gpc = gm20b_fuse_status_opt_gpc, .fuse_status_opt_tpc_gpc = gm20b_fuse_status_opt_tpc_gpc, .fuse_ctrl_opt_tpc_gpc = gm20b_fuse_ctrl_opt_tpc_gpc, + /* Turing is multi-GPC config, static GPC PG to be taken care later */ + .fuse_ctrl_opt_fbp = NULL, + .fuse_ctrl_opt_gpc = NULL, .fuse_opt_sec_debug_en = gm20b_fuse_opt_sec_debug_en, .fuse_opt_priv_sec_en = gm20b_fuse_opt_priv_sec_en, .read_vin_cal_fuse_rev = gp106_fuse_read_vin_cal_fuse_rev, diff --git a/drivers/gpu/nvgpu/hal/vgpu/init/vgpu_hal_gv11b.c b/drivers/gpu/nvgpu/hal/vgpu/init/vgpu_hal_gv11b.c index 3e23bfc57..dae2501c3 100644 --- a/drivers/gpu/nvgpu/hal/vgpu/init/vgpu_hal_gv11b.c +++ b/drivers/gpu/nvgpu/hal/vgpu/init/vgpu_hal_gv11b.c @@ -999,8 +999,11 @@ static const struct gops_fuse vgpu_gv11b_ops_fuse = { .fuse_status_opt_fbio = NULL, .fuse_status_opt_fbp = NULL, .fuse_status_opt_l2_fbp = NULL, + .fuse_status_opt_gpc = NULL, .fuse_status_opt_tpc_gpc = NULL, .fuse_ctrl_opt_tpc_gpc = NULL, + .fuse_ctrl_opt_fbp = NULL, + .fuse_ctrl_opt_gpc = NULL, .fuse_opt_sec_debug_en = NULL, .fuse_opt_priv_sec_en = NULL, .read_vin_cal_fuse_rev = NULL, diff --git a/drivers/gpu/nvgpu/include/nvgpu/gk20a.h b/drivers/gpu/nvgpu/include/nvgpu/gk20a.h index a836c1b35..b91a99e04 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/gk20a.h +++ b/drivers/gpu/nvgpu/include/nvgpu/gk20a.h @@ -149,6 +149,10 @@ enum nvgpu_profiler_pm_reservation_scope; #include +#if defined(CONFIG_NVGPU_NEXT) +#include "nvgpu_next_dt_bindings.h" +#endif + #include "hal/clk/clk_gk20a.h" /** @@ -285,7 +289,19 @@ struct railgate_stats { */ /** @cond DOXYGEN_SHOULD_SKIP_THIS */ +/* MAX_TPC_PG_CONFIGS describes the maximum number of + * valid confiurations we can have for the TPC mask. The valid + * mask is used by SW to write to NV_FUSE_OPT_CTRL_GPC_TPC + * register to powergate the TPC in each GPC + * + * MAX_GPC_FBP_FS_CONFIGS describes the maximum number of + * valid confiurations we can have for the GPC and FBP mask. + * The valid mask is used by SW to write to NV_FUSE_OPT_CTRL_GPC + * NV_FUSE_OPT_CTRL_FBP registers to powergate the GPC and + * floorsweep FBP + */ #define MAX_TPC_PG_CONFIGS 9 +#define MAX_GPC_FBP_FS_CONFIGS 3 struct nvgpu_gpfifo_userdata { struct nvgpu_gpfifo_entry nvgpu_user *entries; @@ -711,8 +727,13 @@ struct gk20a { /** @cond DOXYGEN_SHOULD_SKIP_THIS */ u32 tpc_pg_mask; bool can_tpc_powergate; + u32 fbp_mask; + bool can_fbp_fs; + u32 gpc_mask; + bool can_gpc_fs; u32 valid_tpc_mask[MAX_TPC_PG_CONFIGS]; + u32 valid_gpc_fbp_fs_mask[MAX_GPC_FBP_FS_CONFIGS]; struct nvgpu_bios *bios; bool bios_is_init; diff --git a/drivers/gpu/nvgpu/include/nvgpu/gops/floorsweep.h b/drivers/gpu/nvgpu/include/nvgpu/gops/floorsweep.h index 0bf92f267..88afc42cc 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/gops/floorsweep.h +++ b/drivers/gpu/nvgpu/include/nvgpu/gops/floorsweep.h @@ -27,6 +27,17 @@ struct gops_tpc { int (*init_tpc_powergate)(struct gk20a *g, u32 fuse_status); void (*tpc_gr_pg)(struct gk20a *g); }; + +struct gops_fbp_fs { + int (*init_fbp_floorsweep)(struct gk20a *g, bool *can_fbp_fs); + void (*fbp_static_fs)(struct gk20a *g); +}; + +struct gops_gpc_pg { + int (*init_gpc_powergate)(struct gk20a *g, bool *can_gpc_fs); + void (*gpc_static_pg)(struct gk20a *g); +}; + #endif #endif /* NVGPU_GOPS_FLOORSWEEP_H */ diff --git a/drivers/gpu/nvgpu/include/nvgpu/gops/fuse.h b/drivers/gpu/nvgpu/include/nvgpu/gops/fuse.h index 561071991..c884e681b 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/gops/fuse.h +++ b/drivers/gpu/nvgpu/include/nvgpu/gops/fuse.h @@ -108,6 +108,17 @@ struct gops_fuse { */ u32 (*fuse_status_opt_fbp)(struct gk20a *g); + /** + * @brief Write NV_FUSE_CTRL_OPT_FBP fuse. + * + * @param g [in] The GPU driver struct. + * @param val [in] Fuse value. + * + * The HAL writes NV_FUSE_CTRL_OPT_FBP fuse to floorsweep FBP + * + */ + void (*fuse_ctrl_opt_fbp)(struct gk20a *g, u32 val); + /** * @brief Read NV_FUSE_STATUS_OPT_ROP_L2_FBP fuse. * @@ -184,6 +195,18 @@ struct gops_fuse { */ u32 (*fuse_status_opt_gpc)(struct gk20a *g); + /** + * @brief Write NV_FUSE_CTRL_OPT_GPC fuse. + * + * @param g [in] The GPU driver struct. + * @param val [in] Fuse value. + * + * The HAL writes NV_FUSE_CTRL_OPT_GPC fuse to floorsweep FBP + * + */ + void (*fuse_ctrl_opt_gpc)(struct gk20a *g, u32 val); + + u32 (*fuse_opt_sec_debug_en)(struct gk20a *g); u32 (*read_vin_cal_fuse_rev)(struct gk20a *g); diff --git a/drivers/gpu/nvgpu/include/nvgpu/gpu_ops.h b/drivers/gpu/nvgpu/include/nvgpu/gpu_ops.h index bd88119f6..1c2ce3e46 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/gpu_ops.h +++ b/drivers/gpu/nvgpu/include/nvgpu/gpu_ops.h @@ -220,6 +220,8 @@ struct gpu_ops { /** @endcond */ #ifdef CONFIG_NVGPU_STATIC_POWERGATE struct gops_tpc tpc; + struct gops_fbp_fs fbp_fs; + struct gops_gpc_pg gpc_pg; #endif /** Wake up all threads waiting on semaphore wait. */ void (*semaphore_wakeup)(struct gk20a *g, bool post_events); diff --git a/drivers/gpu/nvgpu/os/linux/driver_common.c b/drivers/gpu/nvgpu/os/linux/driver_common.c index e415668a7..0317a27cf 100644 --- a/drivers/gpu/nvgpu/os/linux/driver_common.c +++ b/drivers/gpu/nvgpu/os/linux/driver_common.c @@ -40,6 +40,9 @@ #include "os_linux.h" #include "sysfs.h" #include "ioctl.h" +#if defined(CONFIG_NVGPU_NEXT) +#include "nvgpu_next_dt_bindings.h" +#endif #define EMC3D_DEFAULT_RATIO 750 @@ -190,6 +193,9 @@ static void nvgpu_init_pm_vars(struct gk20a *g) for (i = 0; i < MAX_TPC_PG_CONFIGS; i++) g->valid_tpc_mask[i] = platform->valid_tpc_mask[i]; + for (i = 0; i < MAX_GPC_FBP_FS_CONFIGS; i++) + g->valid_gpc_fbp_fs_mask[i] = platform->valid_gpc_fbp_fs_mask[i]; + g->ldiv_slowdown_factor = platform->ldiv_slowdown_factor_init; /* if default delay is not set, set default delay to 500msec */ if (platform->railgate_delay_init) diff --git a/drivers/gpu/nvgpu/os/linux/module.c b/drivers/gpu/nvgpu/os/linux/module.c index 2756aaf89..ad05e062b 100644 --- a/drivers/gpu/nvgpu/os/linux/module.c +++ b/drivers/gpu/nvgpu/os/linux/module.c @@ -38,6 +38,8 @@ #include #include +#include + #include #endif /* CONFIG_NVGPU_TEGRA_FUSE */ @@ -1509,6 +1511,19 @@ static int nvgpu_read_fuse_overrides(struct gk20a *g) platform->set_tpc_pg_mask(dev_from_gk20a(g), value); break; + case GA10B_FUSE_OPT_TPC_DISABLE: + /* TBD- JIRA NVGPU-6433 */ + break; + case GA10B_FUSE_OPT_GPC_DISABLE: + if (platform->set_gpc_mask != NULL) + platform->set_gpc_mask(dev_from_gk20a(g), + value); + break; + case GA10B_FUSE_OPT_FBP_DISABLE: + if (platform->set_fbp_mask != NULL) + platform->set_fbp_mask(dev_from_gk20a(g), + value); + break; default: nvgpu_err(g, "ignore unknown fuse override %08x", fuse); break; diff --git a/drivers/gpu/nvgpu/os/linux/platform_gk20a.h b/drivers/gpu/nvgpu/os/linux/platform_gk20a.h index 87c658bda..0d5a188c7 100644 --- a/drivers/gpu/nvgpu/os/linux/platform_gk20a.h +++ b/drivers/gpu/nvgpu/os/linux/platform_gk20a.h @@ -77,6 +77,12 @@ struct gk20a_platform { /* Should be populated at probe. */ bool can_tpc_powergate; + /* Should be populated at probe. */ + bool can_fbp_fs; + + /* Should be populated at probe. */ + bool can_gpc_fs; + /* Should be populated at probe. */ bool can_elpg_init; @@ -108,6 +114,9 @@ struct gk20a_platform { /* valid TPC-MASK */ u32 valid_tpc_mask[MAX_TPC_PG_CONFIGS]; + /* Valid GPC and FBP mask */ + u32 valid_gpc_fbp_fs_mask[MAX_GPC_FBP_FS_CONFIGS]; + /* Delay before rail gated */ int railgate_delay_init; @@ -231,6 +240,12 @@ struct gk20a_platform { /* Set TPC_PG_MASK during probe */ void (*set_tpc_pg_mask)(struct device *dev, u32 tpc_pg_mask); + /* Set GPC_MASK during probe */ + void (*set_gpc_mask)(struct device *dev, u32 gpc_mask); + + /* Set FBP_MASK during probe */ + void (*set_fbp_mask)(struct device *dev, u32 fbp_mask); + /* Devfreq governor name. If scaling is enabled, we request * this governor to be used in scaling */ const char *devfreq_governor; diff --git a/drivers/gpu/nvgpu/os/linux/sysfs.c b/drivers/gpu/nvgpu/os/linux/sysfs.c index 1d88ecff2..f776902bc 100644 --- a/drivers/gpu/nvgpu/os/linux/sysfs.c +++ b/drivers/gpu/nvgpu/os/linux/sysfs.c @@ -50,6 +50,10 @@ #include #endif +#if defined(CONFIG_NVGPU_NEXT) +#include "nvgpu_next_dt_bindings.h" +#endif + #define PTIMER_FP_FACTOR 1000000 #define ROOTRW (S_IRWXU|S_IRGRP|S_IROTH) @@ -842,6 +846,134 @@ static ssize_t tpc_pg_mask_read(struct device *dev, return snprintf(buf, NVGPU_CPU_PAGE_SIZE, "%d\n", g->tpc_pg_mask); } +static bool is_gpc_fbp_mask_valid(struct gk20a *g, u32 fs_mask) +{ + u32 i; + bool valid = false; + + for (i = 0; i < MAX_GPC_FBP_FS_CONFIGS; i++) { + if (fs_mask == g->valid_gpc_fbp_fs_mask[i]) { + valid = true; + break; + } + } + return valid; +} + +static ssize_t gpc_fs_mask_read(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gk20a *g = get_gk20a(dev); + + return snprintf(buf, NVGPU_CPU_PAGE_SIZE, "%d\n", g->gpc_mask); +} + +static ssize_t gpc_fs_mask_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct gk20a *g = get_gk20a(dev); + unsigned long val = 0; + struct nvgpu_gr_obj_ctx_golden_image *gr_golden_image = NULL; + + nvgpu_mutex_acquire(&g->static_pg_lock); + + if (kstrtoul(buf, 10, &val) < 0) { + nvgpu_err(g, "invalid value"); + nvgpu_mutex_release(&g->static_pg_lock); + return -EINVAL; + } + + if (val == g->gpc_mask) { + nvgpu_info(g, "no value change, same mask already set"); + goto exit; + } + + if (g->gr != NULL) { + gr_golden_image = nvgpu_gr_get_golden_image_ptr(g); + } + + if (gr_golden_image && + nvgpu_gr_obj_ctx_get_golden_image_size(gr_golden_image) + != 0) { + nvgpu_err(g, "golden image size already initialized"); + nvgpu_mutex_release(&g->static_pg_lock); + return -ENODEV; + } + /* checking that the value from userspace is within + * the possible valid TPC configurations. + */ + if (is_gpc_fbp_mask_valid(g, (u32)val)) { + g->gpc_mask = val; + } else { + nvgpu_err(g, "GPC FS mask is invalid"); + nvgpu_mutex_release(&g->static_pg_lock); + return -EINVAL; + } +exit: + nvgpu_mutex_release(&g->static_pg_lock); + + return count; +} + +static DEVICE_ATTR(gpc_fs_mask, ROOTRW, gpc_fs_mask_read, gpc_fs_mask_store); + +static ssize_t fbp_fs_mask_read(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct gk20a *g = get_gk20a(dev); + + return snprintf(buf, NVGPU_CPU_PAGE_SIZE, "%d\n", g->fbp_mask); +} + +static ssize_t fbp_fs_mask_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct gk20a *g = get_gk20a(dev); + unsigned long val = 0; + struct nvgpu_gr_obj_ctx_golden_image *gr_golden_image = NULL; + + nvgpu_mutex_acquire(&g->static_pg_lock); + + if (kstrtoul(buf, 10, &val) < 0) { + nvgpu_err(g, "invalid value"); + nvgpu_mutex_release(&g->static_pg_lock); + return -EINVAL; + } + + if (val == g->fbp_mask) { + nvgpu_info(g, "no value change, same mask already set"); + goto exit; + } + + if (g->gr != NULL) { + gr_golden_image = nvgpu_gr_get_golden_image_ptr(g); + } + + if (gr_golden_image && + nvgpu_gr_obj_ctx_get_golden_image_size(gr_golden_image) + != 0) { + nvgpu_err(g, "golden image size already initialized"); + nvgpu_mutex_release(&g->static_pg_lock); + return -ENODEV; + } + /* checking that the value from userspace is within + * the possible valid TPC configurations. + */ + if (is_gpc_fbp_mask_valid(g, (u32)val)) { + g->fbp_mask = val; + } else { + nvgpu_err(g, "FBP FS mask is invalid"); + nvgpu_mutex_release(&g->static_pg_lock); + return -EINVAL; + } +exit: + nvgpu_mutex_release(&g->static_pg_lock); + + return count; +} + +static DEVICE_ATTR(fbp_fs_mask, ROOTRW, fbp_fs_mask_read, fbp_fs_mask_store); + static bool is_tpc_mask_valid(struct gk20a *g, u32 tpc_mask) { u32 i; @@ -1203,6 +1335,8 @@ void nvgpu_remove_sysfs(struct device *dev) device_remove_file(dev, &dev_attr_allow_all); device_remove_file(dev, &dev_attr_tpc_fs_mask); device_remove_file(dev, &dev_attr_tpc_pg_mask); + device_remove_file(dev, &dev_attr_gpc_fs_mask); + device_remove_file(dev, &dev_attr_fbp_fs_mask); device_remove_file(dev, &dev_attr_tsg_timeslice_min_us); device_remove_file(dev, &dev_attr_tsg_timeslice_max_us); @@ -1265,6 +1399,8 @@ int nvgpu_create_sysfs(struct device *dev) error |= device_create_file(dev, &dev_attr_allow_all); error |= device_create_file(dev, &dev_attr_tpc_fs_mask); error |= device_create_file(dev, &dev_attr_tpc_pg_mask); + error |= device_create_file(dev, &dev_attr_gpc_fs_mask); + error |= device_create_file(dev, &dev_attr_fbp_fs_mask); error |= device_create_file(dev, &dev_attr_tsg_timeslice_min_us); error |= device_create_file(dev, &dev_attr_tsg_timeslice_max_us);