mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-22 17:36:20 +03:00
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:
committed by
mobile promotions
parent
9f30609550
commit
842bef7124
@@ -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;
|
||||
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),
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -149,6 +149,10 @@ enum nvgpu_profiler_pm_reservation_scope;
|
||||
|
||||
#include <nvgpu/gpu_ops.h>
|
||||
|
||||
#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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -38,6 +38,8 @@
|
||||
#include <dt-bindings/soc/gp10b-fuse.h>
|
||||
#include <dt-bindings/soc/gv11b-fuse.h>
|
||||
|
||||
#include <dt-bindings/soc/ga10b-fuse.h>
|
||||
|
||||
#include <soc/tegra/fuse.h>
|
||||
#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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -50,6 +50,10 @@
|
||||
#include <nvgpu/device.h>
|
||||
#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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user