gpu: nvgpu: Support GPC and FBP Floorsweeping

- 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 <dsinghatwari@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2499571
Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com>
Reviewed-by: svc-mobile-misra <svc-mobile-misra@nvidia.com>
Reviewed-by: svc-mobile-cert <svc-mobile-cert@nvidia.com>
Reviewed-by: svc_kernel_abi <svc_kernel_abi@nvidia.com>
Reviewed-by: Vijayakumar Subbu <vsubbu@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
GVS: Gerrit_Virtual_Submit
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
Divya Singhatwaria
2021-03-16 22:29:33 +05:30
committed by mobile promotions
parent 9f30609550
commit 842bef7124
14 changed files with 334 additions and 8 deletions

View File

@@ -431,15 +431,47 @@ static int nvgpu_init_fbpa_ecc(struct gk20a *g)
static int nvgpu_init_power_gate(struct gk20a *g) static int nvgpu_init_power_gate(struct gk20a *g)
{ {
int err; 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. * and the fuse_status register.
* If TPC PG mask is invalid halt the GPU poweron. * If TPC PG mask is invalid halt the GPU poweron.
*/ */
g->can_tpc_powergate = false; g->can_tpc_powergate = false;
if (g->ops.fuse.fuse_status_opt_tpc_gpc != NULL) {
fuse_status = g->ops.fuse.fuse_status_opt_tpc_gpc(g, 0); fuse_status = g->ops.fuse.fuse_status_opt_tpc_gpc(g, 0);
}
if (g->ops.tpc.init_tpc_powergate != NULL) { if (g->ops.tpc.init_tpc_powergate != NULL) {
err = g->ops.tpc.init_tpc_powergate(g, fuse_status); 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) 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)) { if (g->can_tpc_powergate && (g->ops.tpc.tpc_gr_pg != NULL)) {
g->ops.tpc.tpc_gr_pg(g); g->ops.tpc.tpc_gr_pg(g);
} }
@@ -632,6 +675,11 @@ static int nvgpu_early_init(struct gk20a *g)
#endif #endif
NVGPU_INIT_TABLE_ENTRY(&nvgpu_init_interrupt_setup, NO_FLAG), NVGPU_INIT_TABLE_ENTRY(&nvgpu_init_interrupt_setup, NO_FLAG),
NVGPU_INIT_TABLE_ENTRY(g->ops.bus.init_hw, 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, NVGPU_INIT_TABLE_ENTRY(g->ops.priv_ring.enable_priv_ring,
NO_FLAG), NO_FLAG),
#ifdef CONFIG_NVGPU_NON_FUSA #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.fifo.fifo_init_support, NO_FLAG),
NVGPU_INIT_TABLE_ENTRY(g->ops.therm.elcg_init_idle_filters, NVGPU_INIT_TABLE_ENTRY(g->ops.therm.elcg_init_idle_filters,
NO_FLAG), 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), NVGPU_INIT_TABLE_ENTRY(&nvgpu_netlist_init_ctx_vars, NO_FLAG),
/* prepare portion of sw required for enable hw */ /* prepare portion of sw required for enable hw */
NVGPU_INIT_TABLE_ENTRY(&nvgpu_gr_alloc, NO_FLAG), NVGPU_INIT_TABLE_ENTRY(&nvgpu_gr_alloc, NO_FLAG),

View File

@@ -1030,7 +1030,10 @@ static const struct gops_fuse gm20b_ops_fuse = {
.fuse_status_opt_fbp = gm20b_fuse_status_opt_fbp, .fuse_status_opt_fbp = gm20b_fuse_status_opt_fbp,
.fuse_status_opt_l2_fbp = gm20b_fuse_status_opt_l2_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_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_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_sec_debug_en = gm20b_fuse_opt_sec_debug_en,
.fuse_opt_priv_sec_en = gm20b_fuse_opt_priv_sec_en, .fuse_opt_priv_sec_en = gm20b_fuse_opt_priv_sec_en,
.read_vin_cal_fuse_rev = NULL, .read_vin_cal_fuse_rev = NULL,
@@ -1056,6 +1059,17 @@ static const struct gops_tpc gm20b_ops_tpc = {
.init_tpc_powergate = NULL, .init_tpc_powergate = NULL,
.tpc_gr_pg = 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 #endif
static const struct gops_grmgr gm20b_ops_grmgr = { static const struct gops_grmgr gm20b_ops_grmgr = {
@@ -1170,6 +1184,8 @@ int gm20b_init_hal(struct gk20a *g)
gops->top = gm20b_ops_top; gops->top = gm20b_ops_top;
#ifdef CONFIG_NVGPU_STATIC_POWERGATE #ifdef CONFIG_NVGPU_STATIC_POWERGATE
gops->tpc = gm20b_ops_tpc; gops->tpc = gm20b_ops_tpc;
gops->fbp_fs = gm20b_ops_fbp_fs;
gops->gpc_pg = gm20b_ops_gpc_pg;
#endif #endif
gops->grmgr = gm20b_ops_grmgr; gops->grmgr = gm20b_ops_grmgr;
gops->cic_mon = gm20b_ops_cic_mon; gops->cic_mon = gm20b_ops_cic_mon;

View File

@@ -1128,7 +1128,10 @@ static const struct gops_fuse gp10b_ops_fuse = {
.fuse_status_opt_fbp = gm20b_fuse_status_opt_fbp, .fuse_status_opt_fbp = gm20b_fuse_status_opt_fbp,
.fuse_status_opt_l2_fbp = gm20b_fuse_status_opt_l2_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_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_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_sec_debug_en = gm20b_fuse_opt_sec_debug_en,
.fuse_opt_priv_sec_en = gm20b_fuse_opt_priv_sec_en, .fuse_opt_priv_sec_en = gm20b_fuse_opt_priv_sec_en,
.read_vin_cal_fuse_rev = NULL, .read_vin_cal_fuse_rev = NULL,
@@ -1155,6 +1158,17 @@ static const struct gops_tpc gp10b_ops_tpc = {
.init_tpc_powergate = NULL, .init_tpc_powergate = NULL,
.tpc_gr_pg = 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 #endif
static const struct gops_grmgr gp10b_ops_grmgr = { static const struct gops_grmgr gp10b_ops_grmgr = {
@@ -1259,6 +1273,8 @@ int gp10b_init_hal(struct gk20a *g)
gops->top = gp10b_ops_top; gops->top = gp10b_ops_top;
#ifdef CONFIG_NVGPU_STATIC_POWERGATE #ifdef CONFIG_NVGPU_STATIC_POWERGATE
gops->tpc = gp10b_ops_tpc; gops->tpc = gp10b_ops_tpc;
gops->fbp_fs = gp10b_ops_fbp_fs;
gops->gpc_pg = gp10b_ops_gpc_pg;
#endif #endif
gops->grmgr = gp10b_ops_grmgr; gops->grmgr = gp10b_ops_grmgr;
gops->cic_mon = gp10b_ops_cic_mon; gops->cic_mon = gp10b_ops_cic_mon;

View File

@@ -1405,8 +1405,11 @@ static const struct gops_fuse gv11b_ops_fuse = {
.fuse_status_opt_fbio = gm20b_fuse_status_opt_fbio, .fuse_status_opt_fbio = gm20b_fuse_status_opt_fbio,
.fuse_status_opt_fbp = gm20b_fuse_status_opt_fbp, .fuse_status_opt_fbp = gm20b_fuse_status_opt_fbp,
.fuse_status_opt_l2_fbp = gm20b_fuse_status_opt_l2_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_status_opt_tpc_gpc = gm20b_fuse_status_opt_tpc_gpc,
.fuse_ctrl_opt_tpc_gpc = gm20b_fuse_ctrl_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_sec_debug_en = gm20b_fuse_opt_sec_debug_en,
.fuse_opt_priv_sec_en = gm20b_fuse_opt_priv_sec_en, .fuse_opt_priv_sec_en = gm20b_fuse_opt_priv_sec_en,
.read_vin_cal_fuse_rev = NULL, .read_vin_cal_fuse_rev = NULL,
@@ -1434,6 +1437,17 @@ static const struct gops_tpc gv11b_ops_tpc = {
.init_tpc_powergate = gv11b_tpc_powergate, .init_tpc_powergate = gv11b_tpc_powergate,
.tpc_gr_pg = gv11b_gr_pg_tpc, .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 #endif
static const struct gops_grmgr gv11b_ops_grmgr = { static const struct gops_grmgr gv11b_ops_grmgr = {
@@ -1539,6 +1553,8 @@ int gv11b_init_hal(struct gk20a *g)
gops->top = gv11b_ops_top; gops->top = gv11b_ops_top;
#ifdef CONFIG_NVGPU_STATIC_POWERGATE #ifdef CONFIG_NVGPU_STATIC_POWERGATE
gops->tpc = gv11b_ops_tpc; gops->tpc = gv11b_ops_tpc;
gops->fbp_fs = gv11b_ops_fbp_fs;
gops->gpc_pg = gv11b_ops_gpc_pg;
#endif #endif
gops->grmgr = gv11b_ops_grmgr; gops->grmgr = gv11b_ops_grmgr;
gops->cic_mon = gv11b_ops_cic_mon; gops->cic_mon = gv11b_ops_cic_mon;

View File

@@ -1510,6 +1510,9 @@ static const struct gops_fuse tu104_ops_fuse = {
.fuse_status_opt_gpc = gm20b_fuse_status_opt_gpc, .fuse_status_opt_gpc = gm20b_fuse_status_opt_gpc,
.fuse_status_opt_tpc_gpc = gm20b_fuse_status_opt_tpc_gpc, .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_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_sec_debug_en = gm20b_fuse_opt_sec_debug_en,
.fuse_opt_priv_sec_en = gm20b_fuse_opt_priv_sec_en, .fuse_opt_priv_sec_en = gm20b_fuse_opt_priv_sec_en,
.read_vin_cal_fuse_rev = gp106_fuse_read_vin_cal_fuse_rev, .read_vin_cal_fuse_rev = gp106_fuse_read_vin_cal_fuse_rev,

View File

@@ -999,8 +999,11 @@ static const struct gops_fuse vgpu_gv11b_ops_fuse = {
.fuse_status_opt_fbio = NULL, .fuse_status_opt_fbio = NULL,
.fuse_status_opt_fbp = NULL, .fuse_status_opt_fbp = NULL,
.fuse_status_opt_l2_fbp = NULL, .fuse_status_opt_l2_fbp = NULL,
.fuse_status_opt_gpc = NULL,
.fuse_status_opt_tpc_gpc = NULL, .fuse_status_opt_tpc_gpc = NULL,
.fuse_ctrl_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_sec_debug_en = NULL,
.fuse_opt_priv_sec_en = NULL, .fuse_opt_priv_sec_en = NULL,
.read_vin_cal_fuse_rev = NULL, .read_vin_cal_fuse_rev = NULL,

View File

@@ -149,6 +149,10 @@ enum nvgpu_profiler_pm_reservation_scope;
#include <nvgpu/gpu_ops.h> #include <nvgpu/gpu_ops.h>
#if defined(CONFIG_NVGPU_NEXT)
#include "nvgpu_next_dt_bindings.h"
#endif
#include "hal/clk/clk_gk20a.h" #include "hal/clk/clk_gk20a.h"
/** /**
@@ -285,7 +289,19 @@ struct railgate_stats {
*/ */
/** @cond DOXYGEN_SHOULD_SKIP_THIS */ /** @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_TPC_PG_CONFIGS 9
#define MAX_GPC_FBP_FS_CONFIGS 3
struct nvgpu_gpfifo_userdata { struct nvgpu_gpfifo_userdata {
struct nvgpu_gpfifo_entry nvgpu_user *entries; struct nvgpu_gpfifo_entry nvgpu_user *entries;
@@ -711,8 +727,13 @@ struct gk20a {
/** @cond DOXYGEN_SHOULD_SKIP_THIS */ /** @cond DOXYGEN_SHOULD_SKIP_THIS */
u32 tpc_pg_mask; u32 tpc_pg_mask;
bool can_tpc_powergate; 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_tpc_mask[MAX_TPC_PG_CONFIGS];
u32 valid_gpc_fbp_fs_mask[MAX_GPC_FBP_FS_CONFIGS];
struct nvgpu_bios *bios; struct nvgpu_bios *bios;
bool bios_is_init; bool bios_is_init;

View File

@@ -27,6 +27,17 @@ struct gops_tpc {
int (*init_tpc_powergate)(struct gk20a *g, u32 fuse_status); int (*init_tpc_powergate)(struct gk20a *g, u32 fuse_status);
void (*tpc_gr_pg)(struct gk20a *g); 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
#endif /* NVGPU_GOPS_FLOORSWEEP_H */ #endif /* NVGPU_GOPS_FLOORSWEEP_H */

View File

@@ -108,6 +108,17 @@ struct gops_fuse {
*/ */
u32 (*fuse_status_opt_fbp)(struct gk20a *g); 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. * @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); 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 (*fuse_opt_sec_debug_en)(struct gk20a *g);
u32 (*read_vin_cal_fuse_rev)(struct gk20a *g); u32 (*read_vin_cal_fuse_rev)(struct gk20a *g);

View File

@@ -220,6 +220,8 @@ struct gpu_ops {
/** @endcond */ /** @endcond */
#ifdef CONFIG_NVGPU_STATIC_POWERGATE #ifdef CONFIG_NVGPU_STATIC_POWERGATE
struct gops_tpc tpc; struct gops_tpc tpc;
struct gops_fbp_fs fbp_fs;
struct gops_gpc_pg gpc_pg;
#endif #endif
/** Wake up all threads waiting on semaphore wait. */ /** Wake up all threads waiting on semaphore wait. */
void (*semaphore_wakeup)(struct gk20a *g, bool post_events); void (*semaphore_wakeup)(struct gk20a *g, bool post_events);

View File

@@ -40,6 +40,9 @@
#include "os_linux.h" #include "os_linux.h"
#include "sysfs.h" #include "sysfs.h"
#include "ioctl.h" #include "ioctl.h"
#if defined(CONFIG_NVGPU_NEXT)
#include "nvgpu_next_dt_bindings.h"
#endif
#define EMC3D_DEFAULT_RATIO 750 #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++) for (i = 0; i < MAX_TPC_PG_CONFIGS; i++)
g->valid_tpc_mask[i] = platform->valid_tpc_mask[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; g->ldiv_slowdown_factor = platform->ldiv_slowdown_factor_init;
/* if default delay is not set, set default delay to 500msec */ /* if default delay is not set, set default delay to 500msec */
if (platform->railgate_delay_init) if (platform->railgate_delay_init)

View File

@@ -38,6 +38,8 @@
#include <dt-bindings/soc/gp10b-fuse.h> #include <dt-bindings/soc/gp10b-fuse.h>
#include <dt-bindings/soc/gv11b-fuse.h> #include <dt-bindings/soc/gv11b-fuse.h>
#include <dt-bindings/soc/ga10b-fuse.h>
#include <soc/tegra/fuse.h> #include <soc/tegra/fuse.h>
#endif /* CONFIG_NVGPU_TEGRA_FUSE */ #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), platform->set_tpc_pg_mask(dev_from_gk20a(g),
value); value);
break; 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: default:
nvgpu_err(g, "ignore unknown fuse override %08x", fuse); nvgpu_err(g, "ignore unknown fuse override %08x", fuse);
break; break;

View File

@@ -77,6 +77,12 @@ struct gk20a_platform {
/* Should be populated at probe. */ /* Should be populated at probe. */
bool can_tpc_powergate; 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. */ /* Should be populated at probe. */
bool can_elpg_init; bool can_elpg_init;
@@ -108,6 +114,9 @@ struct gk20a_platform {
/* valid TPC-MASK */ /* valid TPC-MASK */
u32 valid_tpc_mask[MAX_TPC_PG_CONFIGS]; 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 */ /* Delay before rail gated */
int railgate_delay_init; int railgate_delay_init;
@@ -231,6 +240,12 @@ struct gk20a_platform {
/* Set TPC_PG_MASK during probe */ /* Set TPC_PG_MASK during probe */
void (*set_tpc_pg_mask)(struct device *dev, u32 tpc_pg_mask); 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 /* Devfreq governor name. If scaling is enabled, we request
* this governor to be used in scaling */ * this governor to be used in scaling */
const char *devfreq_governor; const char *devfreq_governor;

View File

@@ -50,6 +50,10 @@
#include <nvgpu/device.h> #include <nvgpu/device.h>
#endif #endif
#if defined(CONFIG_NVGPU_NEXT)
#include "nvgpu_next_dt_bindings.h"
#endif
#define PTIMER_FP_FACTOR 1000000 #define PTIMER_FP_FACTOR 1000000
#define ROOTRW (S_IRWXU|S_IRGRP|S_IROTH) #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); 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) static bool is_tpc_mask_valid(struct gk20a *g, u32 tpc_mask)
{ {
u32 i; 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_allow_all);
device_remove_file(dev, &dev_attr_tpc_fs_mask); device_remove_file(dev, &dev_attr_tpc_fs_mask);
device_remove_file(dev, &dev_attr_tpc_pg_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_min_us);
device_remove_file(dev, &dev_attr_tsg_timeslice_max_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_allow_all);
error |= device_create_file(dev, &dev_attr_tpc_fs_mask); 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_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_min_us);
error |= device_create_file(dev, &dev_attr_tsg_timeslice_max_us); error |= device_create_file(dev, &dev_attr_tsg_timeslice_max_us);