mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-22 09:12:24 +03:00
gpu: nvgpu: add platform support for Static PG
- Add support for taking static PG config values from DT nodes - Check those values against valid set of values for GPC, TPC and FBP - Store valid values in g->gpc_pg_mask, g->fbp_pg_mask and g->tpc_pg_mask[] array. Bug 200768322 JIRA NVGPU-6433 Change-Id: Ifc87e7d369034b1daa13866bc16a970602514bf6 Signed-off-by: Divya <dsinghatwari@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2594802 Reviewed-by: Vijayakumar Subbu <vsubbu@nvidia.com> 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: mobile promotions <svcmobile_promotions@nvidia.com> GVS: Gerrit_Virtual_Submit Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
@@ -436,7 +436,6 @@ 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 = 0x0;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pre-Silicon - Static pg feature related settings
|
* Pre-Silicon - Static pg feature related settings
|
||||||
@@ -478,12 +477,8 @@ static int nvgpu_init_power_gate(struct gk20a *g)
|
|||||||
* halt the GPU poweron.
|
* halt the GPU poweron.
|
||||||
*/
|
*/
|
||||||
g->can_tpc_pg = false;
|
g->can_tpc_pg = 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_pg.init_tpc_pg != NULL) {
|
if (g->ops.tpc_pg.init_tpc_pg != NULL) {
|
||||||
err = g->ops.tpc_pg.init_tpc_pg(g, fuse_status);
|
err = g->ops.tpc_pg.init_tpc_pg(g, &g->can_tpc_pg);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -518,7 +513,7 @@ static int nvgpu_init_power_gate_gr(struct gk20a *g)
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* CONFIG_NVGPU_STATIC_POWERGATE */
|
||||||
|
|
||||||
static int nvgpu_init_boot_clk_or_clk_arb(struct gk20a *g)
|
static int nvgpu_init_boot_clk_or_clk_arb(struct gk20a *g)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1637,7 +1637,7 @@ static const struct gops_tpc_pg ga10b_ops_tpc_pg = {
|
|||||||
* HALs for static-pg will be updated
|
* HALs for static-pg will be updated
|
||||||
* for pre-silicon platform during HAL init.
|
* for pre-silicon platform during HAL init.
|
||||||
* For silicon, static-pg feature related settings
|
* For silicon, static-pg feature related settings
|
||||||
* will be taken care of by BPMP.
|
* will be taken care by BPMP.
|
||||||
* Silicon: assigining the HALs to NULL.
|
* Silicon: assigining the HALs to NULL.
|
||||||
* Pre-Silicon: To-do JIRA-NVGPU-7112
|
* Pre-Silicon: To-do JIRA-NVGPU-7112
|
||||||
* to add these HALs
|
* to add these HALs
|
||||||
@@ -1757,8 +1757,8 @@ int ga10b_init_hal(struct gk20a *g)
|
|||||||
gops->priv_ring = ga10b_ops_priv_ring;
|
gops->priv_ring = ga10b_ops_priv_ring;
|
||||||
gops->fuse = ga10b_ops_fuse;
|
gops->fuse = ga10b_ops_fuse;
|
||||||
gops->top = ga10b_ops_top;
|
gops->top = ga10b_ops_top;
|
||||||
#ifdef CONFIG_NVGPU_TPC_POWERGATE
|
#ifdef CONFIG_NVGPU_STATIC_POWERGATE
|
||||||
gops->tpc = ga10b_ops_tpc;
|
gops->tpc_pg = ga10b_ops_tpc_pg;
|
||||||
#endif
|
#endif
|
||||||
gops->grmgr = ga10b_ops_grmgr;
|
gops->grmgr = ga10b_ops_grmgr;
|
||||||
gops->chip_init_gpu_characteristics = ga10b_init_gpu_characteristics;
|
gops->chip_init_gpu_characteristics = ga10b_init_gpu_characteristics;
|
||||||
|
|||||||
@@ -24,32 +24,52 @@
|
|||||||
#include <nvgpu/gk20a.h>
|
#include <nvgpu/gk20a.h>
|
||||||
#include "tpc_gv11b.h"
|
#include "tpc_gv11b.h"
|
||||||
|
|
||||||
int gv11b_tpc_pg(struct gk20a *g, u32 fuse_status)
|
#ifdef CONFIG_NVGPU_STATIC_POWERGATE
|
||||||
|
/*
|
||||||
|
* validate the requested tpc pg mask
|
||||||
|
* with respect to the current hw value.
|
||||||
|
*/
|
||||||
|
int gv11b_tpc_pg(struct gk20a *g, bool *can_tpc_pg)
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
u32 fuse_status = 0x0;
|
||||||
|
|
||||||
|
if (g->ops.fuse.fuse_status_opt_tpc_gpc != NULL) {
|
||||||
|
fuse_status = g->ops.fuse.fuse_status_opt_tpc_gpc(g, 0);
|
||||||
|
}
|
||||||
|
|
||||||
if (fuse_status == 0x0) {
|
if (fuse_status == 0x0) {
|
||||||
g->can_tpc_pg = true;
|
/*
|
||||||
|
* fuse_status = 0x0 means all TPCs are active
|
||||||
|
* thus, tpc_pg_mask passed by user or DT
|
||||||
|
* can be applied to powergate the TPC(s).
|
||||||
|
*/
|
||||||
|
*can_tpc_pg = true;
|
||||||
} else {
|
} else {
|
||||||
/* if hardware has already floorswept any TPC
|
/* if hardware has already floorswept any TPC
|
||||||
* (fuse_status != 0x0) and if TPC PG mask
|
* (fuse_status != 0x0) and if TPC PG mask
|
||||||
* sent from userspace is 0x0 GPU will be powered on
|
* sent from userspace/DT node is 0x0 (it is trying to
|
||||||
* with the default fuse_status setting. It cannot
|
* set all TPCs active), GPU will be powered on
|
||||||
* un-floorsweep any TPC
|
* with the default HW fuse_status setting. It cannot
|
||||||
|
* un-floorsweep any TPC.
|
||||||
* thus, set g->tpc_pg_mask to fuse_status value
|
* thus, set g->tpc_pg_mask to fuse_status value
|
||||||
|
* and boot with default HW fuse settings.
|
||||||
*/
|
*/
|
||||||
if (g->tpc_pg_mask == 0x0) {
|
if (g->tpc_pg_mask[PG_GPC0] == 0x0U) {
|
||||||
g->can_tpc_pg = true;
|
*can_tpc_pg = true;
|
||||||
g->tpc_pg_mask = fuse_status;
|
g->tpc_pg_mask[PG_GPC0] = fuse_status;
|
||||||
|
|
||||||
} else if (fuse_status == g->tpc_pg_mask) {
|
} else if (fuse_status == g->tpc_pg_mask[PG_GPC0]) {
|
||||||
g->can_tpc_pg = true;
|
*can_tpc_pg = true;
|
||||||
|
|
||||||
} else if ((fuse_status & g->tpc_pg_mask) ==
|
} else if ((fuse_status & g->tpc_pg_mask[PG_GPC0]) ==
|
||||||
fuse_status) {
|
fuse_status) {
|
||||||
g->can_tpc_pg = true;
|
/*
|
||||||
|
* if HW has already floorswept any TPC
|
||||||
|
* check if the tpc_pg_mask sent by user
|
||||||
|
* is floorsweeping only additional TPCs
|
||||||
|
*/
|
||||||
|
*can_tpc_pg = true;
|
||||||
} else {
|
} else {
|
||||||
/* If userspace sends a TPC PG mask such that
|
/* If userspace sends a TPC PG mask such that
|
||||||
* it tries to un-floorsweep any TPC which is
|
* it tries to un-floorsweep any TPC which is
|
||||||
@@ -59,9 +79,9 @@ int gv11b_tpc_pg(struct gk20a *g, u32 fuse_status)
|
|||||||
* Return -EINVAL here and halt GPU poweron.
|
* Return -EINVAL here and halt GPU poweron.
|
||||||
*/
|
*/
|
||||||
nvgpu_err(g, "Invalid TPC_PG mask: 0x%x",
|
nvgpu_err(g, "Invalid TPC_PG mask: 0x%x",
|
||||||
g->tpc_pg_mask);
|
g->tpc_pg_mask[PG_GPC0]);
|
||||||
g->can_tpc_pg = false;
|
*can_tpc_pg = false;
|
||||||
g->tpc_pg_mask = 0x0;
|
g->tpc_pg_mask[PG_GPC0] = 0x0;
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -69,19 +89,36 @@ int gv11b_tpc_pg(struct gk20a *g, u32 fuse_status)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* To-do: check to rename this function */
|
||||||
void gv11b_gr_pg_tpc(struct gk20a *g)
|
void gv11b_gr_pg_tpc(struct gk20a *g)
|
||||||
{
|
{
|
||||||
u32 tpc_pg_status = g->ops.fuse.fuse_status_opt_tpc_gpc(g, 0);
|
u32 tpc_pg_status = g->ops.fuse.fuse_status_opt_tpc_gpc(g, PG_GPC0);
|
||||||
|
|
||||||
if (tpc_pg_status == g->tpc_pg_mask) {
|
/*
|
||||||
|
* if the fuse status for tpc is same as tpc_pg_mask
|
||||||
|
* passed, then do nothing and return
|
||||||
|
*/
|
||||||
|
if (tpc_pg_status == g->tpc_pg_mask[PG_GPC0]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
g->ops.fuse.fuse_ctrl_opt_tpc_gpc(g, 0, g->tpc_pg_mask);
|
/*
|
||||||
|
* write to fuse_ctrl register to update the fuse settings
|
||||||
|
* as per the tpc_pg_mask
|
||||||
|
*/
|
||||||
|
g->ops.fuse.fuse_ctrl_opt_tpc_gpc(g, PG_GPC0,
|
||||||
|
g->tpc_pg_mask[PG_GPC0]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* To confirm that the write was successful
|
||||||
|
* read the fuse_status register.
|
||||||
|
* The write done is previous step may take some time to
|
||||||
|
* get update in fuse_status register
|
||||||
|
*/
|
||||||
do {
|
do {
|
||||||
tpc_pg_status = g->ops.fuse.fuse_status_opt_tpc_gpc(g, 0);
|
tpc_pg_status = g->ops.fuse.fuse_status_opt_tpc_gpc(g, PG_GPC0);
|
||||||
} while (tpc_pg_status != g->tpc_pg_mask);
|
} while (tpc_pg_status != g->tpc_pg_mask[PG_GPC0]);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -25,10 +25,12 @@
|
|||||||
#ifndef NVGPU_TPC_GV11B_H
|
#ifndef NVGPU_TPC_GV11B_H
|
||||||
#define NVGPU_TPC_GV11B_H
|
#define NVGPU_TPC_GV11B_H
|
||||||
|
|
||||||
|
#ifdef CONFIG_NVGPU_STATIC_POWERGATE
|
||||||
struct gk20a;
|
struct gk20a;
|
||||||
|
|
||||||
int gv11b_tpc_pg(struct gk20a *g, u32 fuse_status);
|
int gv11b_tpc_pg(struct gk20a *g, bool *can_tpc_pg);
|
||||||
void gv11b_gr_pg_tpc(struct gk20a *g);
|
void gv11b_gr_pg_tpc(struct gk20a *g);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* NVGPU_TPC_GV11B_H */
|
#endif /* NVGPU_TPC_GV11B_H */
|
||||||
|
|
||||||
|
|||||||
@@ -287,21 +287,24 @@ struct railgate_stats {
|
|||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @cond DOXYGEN_SHOULD_SKIP_THIS */
|
/** @cond DOXYGEN_SHOULD_SKIP_THIS */
|
||||||
/* MAX_TPC_PG_CONFIGS describes the maximum number of
|
#ifdef CONFIG_NVGPU_STATIC_POWERGATE
|
||||||
* valid confiurations we can have for the TPC mask. The valid
|
#define MAX_PG_GPC 2
|
||||||
* mask is used by SW to write to NV_FUSE_OPT_CTRL_GPC_TPC
|
#define MAX_TPC_PER_GPC 4
|
||||||
* register to powergate the TPC in each GPC
|
#define PG_GPC0 0
|
||||||
*
|
#define PG_GPC1 1
|
||||||
* MAX_GPC_FBP_FS_CONFIGS describes the maximum number of
|
/*
|
||||||
* valid confiurations we can have for the GPC and FBP mask.
|
* MAX_PG_TPC_CONFIGS describes the maximum number of
|
||||||
* The valid mask is used by SW to write to NV_FUSE_OPT_CTRL_GPC
|
* valid configurations we can have for the TPC mask.
|
||||||
* NV_FUSE_OPT_CTRL_FBP registers to powergate the GPC and
|
|
||||||
* floorsweep FBP
|
|
||||||
*/
|
*/
|
||||||
#define MAX_TPC_PG_CONFIGS 9
|
#define MAX_PG_TPC_CONFIGS (0x1 << MAX_TPC_PER_GPC)
|
||||||
#define MAX_GPC_FBP_FS_CONFIGS 3
|
/*
|
||||||
|
* MAX_PG_GPC_FBP_CONFIGS describes the maximum number of
|
||||||
|
* valid configurations we can have for the GPC and FBP mask.
|
||||||
|
*/
|
||||||
|
#define MAX_PG_GPC_FBP_CONFIGS ((0x1 << MAX_PG_GPC) - 1)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
struct nvgpu_gpfifo_userdata {
|
struct nvgpu_gpfifo_userdata {
|
||||||
struct nvgpu_gpfifo_entry nvgpu_user *entries;
|
struct nvgpu_gpfifo_entry nvgpu_user *entries;
|
||||||
@@ -724,17 +727,25 @@ struct gk20a {
|
|||||||
u32 fecs_feature_override_ecc_val;
|
u32 fecs_feature_override_ecc_val;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_NVGPU_STATIC_POWERGATE
|
||||||
/** @cond DOXYGEN_SHOULD_SKIP_THIS */
|
/** @cond DOXYGEN_SHOULD_SKIP_THIS */
|
||||||
u32 tpc_pg_mask;
|
/* tpc pg mask array for available GPCs */
|
||||||
|
u32 tpc_pg_mask[MAX_PG_GPC];
|
||||||
u32 fbp_pg_mask;
|
u32 fbp_pg_mask;
|
||||||
u32 gpc_pg_mask;
|
u32 gpc_pg_mask;
|
||||||
bool can_tpc_pg;
|
bool can_tpc_pg;
|
||||||
bool can_fbp_pg;
|
bool can_fbp_pg;
|
||||||
bool can_gpc_pg;
|
bool can_gpc_pg;
|
||||||
|
|
||||||
u32 valid_tpc_mask[MAX_TPC_PG_CONFIGS];
|
/*
|
||||||
u32 valid_gpc_fbp_fs_mask[MAX_GPC_FBP_FS_CONFIGS];
|
* Valid config array for tpc pg mask
|
||||||
|
* and gpc/fbp mask. These valid values
|
||||||
|
* are chip specific and calculated based
|
||||||
|
* on available number of GPC, FBP and TPC
|
||||||
|
*/
|
||||||
|
u32 valid_tpc_pg_mask[MAX_PG_TPC_CONFIGS];
|
||||||
|
u32 valid_gpc_fbp_pg_mask[MAX_PG_GPC_FBP_CONFIGS];
|
||||||
|
#endif
|
||||||
struct nvgpu_bios *bios;
|
struct nvgpu_bios *bios;
|
||||||
bool bios_is_init;
|
bool bios_is_init;
|
||||||
|
|
||||||
|
|||||||
@@ -24,17 +24,17 @@
|
|||||||
|
|
||||||
#ifdef CONFIG_NVGPU_STATIC_POWERGATE
|
#ifdef CONFIG_NVGPU_STATIC_POWERGATE
|
||||||
struct gops_tpc_pg {
|
struct gops_tpc_pg {
|
||||||
int (*init_tpc_pg)(struct gk20a *g, u32 fuse_status);
|
int (*init_tpc_pg)(struct gk20a *g, bool *can_tpc_pg);
|
||||||
void (*tpc_pg)(struct gk20a *g);
|
void (*tpc_pg)(struct gk20a *g);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct gops_fbp_pg {
|
struct gops_fbp_pg {
|
||||||
int (*init_fbp_pg)(struct gk20a *g, bool *can_fbp_fs);
|
int (*init_fbp_pg)(struct gk20a *g, bool *can_fbp_pg);
|
||||||
void (*fbp_pg)(struct gk20a *g);
|
void (*fbp_pg)(struct gk20a *g);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct gops_gpc_pg {
|
struct gops_gpc_pg {
|
||||||
int (*init_gpc_pg)(struct gk20a *g, bool *can_gpc_fs);
|
int (*init_gpc_pg)(struct gk20a *g, bool *can_gpc_pg);
|
||||||
void (*gpc_pg)(struct gk20a *g);
|
void (*gpc_pg)(struct gk20a *g);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -184,14 +184,17 @@ static void nvgpu_init_pm_vars(struct gk20a *g)
|
|||||||
|
|
||||||
nvgpu_set_enabled(g, NVGPU_CAN_RAILGATE,
|
nvgpu_set_enabled(g, NVGPU_CAN_RAILGATE,
|
||||||
nvgpu_platform_is_simulation(g)? true : platform->can_railgate_init);
|
nvgpu_platform_is_simulation(g)? true : platform->can_railgate_init);
|
||||||
|
#ifdef CONFIG_NVGPU_STATIC_POWERGATE
|
||||||
g->can_tpc_pg = platform->can_tpc_pg;
|
g->can_tpc_pg = platform->can_tpc_pg;
|
||||||
|
g->can_gpc_pg = platform->can_gpc_pg;
|
||||||
|
g->can_fbp_pg = platform->can_fbp_pg;
|
||||||
|
|
||||||
for (i = 0; i < MAX_TPC_PG_CONFIGS; i++)
|
for (i = 0; i < MAX_PG_TPC_CONFIGS; i++)
|
||||||
g->valid_tpc_mask[i] = platform->valid_tpc_mask[i];
|
g->valid_tpc_pg_mask[i] = platform->valid_tpc_pg_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];
|
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_PG_GPC_FBP_CONFIGS; i++)
|
||||||
|
g->valid_gpc_fbp_pg_mask[i] = platform->valid_gpc_fbp_pg_mask[i];
|
||||||
|
#endif
|
||||||
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)
|
||||||
|
|||||||
@@ -1588,6 +1588,7 @@ static int nvgpu_read_fuse_overrides(struct gk20a *g)
|
|||||||
struct gk20a_platform *platform = dev_get_drvdata(dev_from_gk20a(g));
|
struct gk20a_platform *platform = dev_get_drvdata(dev_from_gk20a(g));
|
||||||
u32 *fuses;
|
u32 *fuses;
|
||||||
int count, i;
|
int count, i;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
if (!np) /* may be pcie device */
|
if (!np) /* may be pcie device */
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1612,24 +1613,44 @@ static int nvgpu_read_fuse_overrides(struct gk20a *g)
|
|||||||
case GP10B_FUSE_OPT_ECC_EN:
|
case GP10B_FUSE_OPT_ECC_EN:
|
||||||
g->fecs_feature_override_ecc_val = value;
|
g->fecs_feature_override_ecc_val = value;
|
||||||
break;
|
break;
|
||||||
|
#ifdef CONFIG_NVGPU_STATIC_POWERGATE
|
||||||
case GV11B_FUSE_OPT_TPC_DISABLE:
|
case GV11B_FUSE_OPT_TPC_DISABLE:
|
||||||
if (platform->set_tpc_pg_mask != NULL)
|
if (platform->set_tpc_pg_mask != NULL) {
|
||||||
platform->set_tpc_pg_mask(dev_from_gk20a(g),
|
ret = platform->set_tpc_pg_mask(dev_from_gk20a(g),
|
||||||
value);
|
value);
|
||||||
|
if (ret != 0) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case GA10B_FUSE_OPT_TPC_DISABLE:
|
case GA10B_FUSE_OPT_TPC_DISABLE:
|
||||||
/* TBD- JIRA NVGPU-6433 */
|
if (platform->set_tpc_pg_mask != NULL) {
|
||||||
|
ret = platform->set_tpc_pg_mask(dev_from_gk20a(g),
|
||||||
|
value);
|
||||||
|
if (ret != 0) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case GA10B_FUSE_OPT_GPC_DISABLE:
|
case GA10B_FUSE_OPT_GPC_DISABLE:
|
||||||
if (platform->set_gpc_mask != NULL)
|
if (platform->set_gpc_pg_mask != NULL) {
|
||||||
platform->set_gpc_mask(dev_from_gk20a(g),
|
ret = platform->set_gpc_pg_mask(dev_from_gk20a(g),
|
||||||
value);
|
value);
|
||||||
|
if (ret != 0) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case GA10B_FUSE_OPT_FBP_DISABLE:
|
case GA10B_FUSE_OPT_FBP_DISABLE:
|
||||||
if (platform->set_fbp_mask != NULL)
|
if (platform->set_fbp_pg_mask != NULL) {
|
||||||
platform->set_fbp_mask(dev_from_gk20a(g),
|
ret = platform->set_fbp_pg_mask(dev_from_gk20a(g),
|
||||||
value);
|
value);
|
||||||
|
if (ret != 0) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
nvgpu_err(g, "ignore unknown fuse override %08x", fuse);
|
nvgpu_err(g, "ignore unknown fuse override %08x", fuse);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -281,13 +281,19 @@ static int ga10b_tegra_suspend(struct device *dev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool is_tpc_mask_valid(struct gk20a_platform *platform, u32 tpc_pg_mask)
|
#ifdef CONFIG_NVGPU_STATIC_POWERGATE
|
||||||
|
static bool ga10b_tegra_is_gpc_fbp_pg_mask_valid(struct gk20a_platform *platform,
|
||||||
|
u32 dt_gpc_fbp_pg_mask)
|
||||||
{
|
{
|
||||||
u32 i;
|
u32 i;
|
||||||
bool valid = false;
|
bool valid = false;
|
||||||
|
|
||||||
for (i = 0; i < MAX_TPC_PG_CONFIGS; i++) {
|
for (i = 0U; i < MAX_PG_GPC_FBP_CONFIGS; i++) {
|
||||||
if (tpc_pg_mask == platform->valid_tpc_mask[i]) {
|
/*
|
||||||
|
* check if gpc/fbp pg mask passed by DT node
|
||||||
|
* is valid gpc/fbp pg mask
|
||||||
|
*/
|
||||||
|
if (dt_gpc_fbp_pg_mask == platform->valid_gpc_fbp_pg_mask[i]) {
|
||||||
valid = true;
|
valid = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -295,16 +301,162 @@ static bool is_tpc_mask_valid(struct gk20a_platform *platform, u32 tpc_pg_mask)
|
|||||||
return valid;
|
return valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ga10b_tegra_set_tpc_pg_mask(struct device *dev, u32 tpc_pg_mask)
|
static int ga10b_tegra_set_gpc_pg_mask(struct device *dev, u32 dt_gpc_pg_mask)
|
||||||
{
|
{
|
||||||
struct gk20a_platform *platform = gk20a_get_platform(dev);
|
struct gk20a_platform *platform = gk20a_get_platform(dev);
|
||||||
struct gk20a *g = get_gk20a(dev);
|
struct gk20a *g = get_gk20a(dev);
|
||||||
|
|
||||||
if (is_tpc_mask_valid(platform, tpc_pg_mask)) {
|
if (ga10b_tegra_is_gpc_fbp_pg_mask_valid(platform, dt_gpc_pg_mask)) {
|
||||||
g->tpc_pg_mask = tpc_pg_mask;
|
g->gpc_pg_mask = dt_gpc_pg_mask;
|
||||||
|
/*
|
||||||
|
* update FBP PG mask same as GPC PG mask
|
||||||
|
* as there is 1:1 mapping for GPC and FBP
|
||||||
|
*/
|
||||||
|
g->fbp_pg_mask = dt_gpc_pg_mask;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
nvgpu_err(g, "Invalid GPC-PG mask");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ga10b_tegra_set_fbp_pg_mask(struct device *dev, u32 dt_fbp_pg_mask)
|
||||||
|
{
|
||||||
|
struct gk20a_platform *platform = gk20a_get_platform(dev);
|
||||||
|
struct gk20a *g = get_gk20a(dev);
|
||||||
|
|
||||||
|
if (ga10b_tegra_is_gpc_fbp_pg_mask_valid(platform, dt_fbp_pg_mask)) {
|
||||||
|
g->fbp_pg_mask = dt_fbp_pg_mask;
|
||||||
|
/*
|
||||||
|
* update GPC PG mask same as FBP PG mask
|
||||||
|
* as there is 1:1 mapping for GPC and FBP
|
||||||
|
*/
|
||||||
|
g->gpc_pg_mask = dt_fbp_pg_mask;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
nvgpu_err(g, "Invalid FBP-PG mask");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ga10b_tegra_set_valid_tpc_pg_mask(struct gk20a_platform *platform)
|
||||||
|
{
|
||||||
|
u32 i;
|
||||||
|
|
||||||
|
for (i = 0U; i < MAX_PG_TPC_CONFIGS; i++) {
|
||||||
|
/*
|
||||||
|
* There are 4 TPCs in each GPC in ga10b
|
||||||
|
* thus, valid tpc pg mask ranges from
|
||||||
|
* 0x0 to 0xF
|
||||||
|
* 0XF will powergate all TPCs, but this
|
||||||
|
* value will be re-checked again as per the
|
||||||
|
* the GPC-PG mask
|
||||||
|
*/
|
||||||
|
platform->valid_tpc_pg_mask[i] = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ga10b_tegra_set_tpc_pg_mask(struct device *dev, u32 dt_tpc_pg_mask)
|
||||||
|
{
|
||||||
|
struct gk20a *g = get_gk20a(dev);
|
||||||
|
struct gk20a_platform *platform = gk20a_get_platform(dev);
|
||||||
|
u32 i, j;
|
||||||
|
bool pg_status, valid = false;
|
||||||
|
/* Hold tpc pg mask value for validation */
|
||||||
|
u32 tmp_tpc_pg_mask[MAX_PG_GPC];
|
||||||
|
/* Hold user requested combined tpc pg mask value */
|
||||||
|
u32 combined_tpc_pg_mask;
|
||||||
|
|
||||||
|
/* first set the valid masks ranges for tpc pg */
|
||||||
|
ga10b_tegra_set_valid_tpc_pg_mask(platform);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if tpc pg mask sent from DT node tries
|
||||||
|
* to powergate all the TPCs in both GPC0 and GPC1
|
||||||
|
* then it is inavlid pg config
|
||||||
|
*/
|
||||||
|
if (dt_tpc_pg_mask == 0xFF) {
|
||||||
|
nvgpu_err(g, "Invalid TPC_PG_MASK:0x%x", dt_tpc_pg_mask);
|
||||||
|
return -EINVAL;
|
||||||
|
} else {
|
||||||
|
/* store dt_tpc_pg_mask in a temp variable */
|
||||||
|
combined_tpc_pg_mask = dt_tpc_pg_mask;
|
||||||
|
|
||||||
|
/* separately store tpc pg mask in a temp array */
|
||||||
|
for (i = 0U; i < MAX_PG_GPC; i++) {
|
||||||
|
tmp_tpc_pg_mask[i] = (combined_tpc_pg_mask >> (4*i)) & 0xFU;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if the tpc pg mask sent from DT is valid or not */
|
||||||
|
for (i = 0U ; i < MAX_PG_GPC; i++) {
|
||||||
|
for (j = 0U; j < MAX_PG_TPC_CONFIGS; j++) {
|
||||||
|
if (tmp_tpc_pg_mask[i] == platform->valid_tpc_pg_mask[j]) {
|
||||||
|
/* store the valid config */
|
||||||
|
g->tpc_pg_mask[i] = tmp_tpc_pg_mask[i];
|
||||||
|
valid = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (valid == false) {
|
||||||
|
nvgpu_err(g, "Invalid TPC PG mask: 0x%x",
|
||||||
|
tmp_tpc_pg_mask[i]);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* check if all TPCs of a GPC are powergated
|
||||||
|
* then powergate the corresponding GPC
|
||||||
|
*/
|
||||||
|
for (i = 0U; i < MAX_PG_GPC; i++) {
|
||||||
|
if (g->tpc_pg_mask[i] == 0xFU) {
|
||||||
|
g->gpc_pg_mask = (0x1U << i);
|
||||||
|
g->fbp_pg_mask = (0x1U << i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If any one GPC is already floorswept
|
||||||
|
* then all the TPCs in that GPC are floorswept
|
||||||
|
* based on gpc_mask update the tpc_pg_mask
|
||||||
|
*/
|
||||||
|
switch (g->gpc_pg_mask) {
|
||||||
|
case 0x0: /* do nothing as all GPCs are active */
|
||||||
|
break;
|
||||||
|
case 0x1:
|
||||||
|
g->tpc_pg_mask[PG_GPC0] = 0xFU;
|
||||||
|
break;
|
||||||
|
case 0x2:
|
||||||
|
g->tpc_pg_mask[PG_GPC1] = 0xFU;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
nvgpu_err(g, "Invalid GPC PG mask: 0x%x",
|
||||||
|
g->gpc_pg_mask);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If both GPC0_TPC and GPC1_TPC mask are 0xF
|
||||||
|
* then it is invalid as we cannot powergate
|
||||||
|
* all the TPCs on the chip. This is invalid
|
||||||
|
* configuration
|
||||||
|
*/
|
||||||
|
for (i = 0U; i < MAX_PG_GPC; i++) {
|
||||||
|
if (g->tpc_pg_mask[i] == 0xF) {
|
||||||
|
pg_status = true;
|
||||||
|
} else {
|
||||||
|
pg_status = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pg_status == true) {
|
||||||
|
nvgpu_err(g, "Disabling all TPCs isn't allowed!");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
struct gk20a_platform ga10b_tegra_platform = {
|
struct gk20a_platform ga10b_tegra_platform = {
|
||||||
#ifdef CONFIG_TEGRA_GK20A_NVHOST
|
#ifdef CONFIG_TEGRA_GK20A_NVHOST
|
||||||
.has_syncpoints = true,
|
.has_syncpoints = true,
|
||||||
@@ -321,11 +473,28 @@ struct gk20a_platform ga10b_tegra_platform = {
|
|||||||
.railgate_delay_init = 500,
|
.railgate_delay_init = 500,
|
||||||
.can_railgate_init = false,
|
.can_railgate_init = false,
|
||||||
|
|
||||||
|
#ifdef CONFIG_NVGPU_STATIC_POWERGATE
|
||||||
/* add tpc powergate JIRA NVGPU-4683 */
|
/* add tpc powergate JIRA NVGPU-4683 */
|
||||||
.can_tpc_pg = false,
|
.can_tpc_pg = false,
|
||||||
|
.can_gpc_pg = false,
|
||||||
|
.can_fbp_pg = false,
|
||||||
|
|
||||||
.set_tpc_pg_mask = ga10b_tegra_set_tpc_pg_mask,
|
/*
|
||||||
|
* there are 2 GPCs and 2 FBPs
|
||||||
|
* so the valid config to powergate
|
||||||
|
* is 0x0 (all active)
|
||||||
|
* 0x1 (GPC1/FBP1 active)
|
||||||
|
* 0x2 (GPC0/FBP0 active)
|
||||||
|
* 0x3 (both powergated) becomes invalid
|
||||||
|
*/
|
||||||
|
.valid_gpc_fbp_pg_mask[0] = 0x0,
|
||||||
|
.valid_gpc_fbp_pg_mask[1] = 0x1,
|
||||||
|
.valid_gpc_fbp_pg_mask[2] = 0x2,
|
||||||
|
|
||||||
|
.set_tpc_pg_mask = ga10b_tegra_set_tpc_pg_mask,
|
||||||
|
.set_gpc_pg_mask = ga10b_tegra_set_gpc_pg_mask,
|
||||||
|
.set_fbp_pg_mask = ga10b_tegra_set_fbp_pg_mask,
|
||||||
|
#endif
|
||||||
.can_slcg = true,
|
.can_slcg = true,
|
||||||
.can_blcg = true,
|
.can_blcg = true,
|
||||||
.can_elcg = true,
|
.can_elcg = true,
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ struct gk20a_platform {
|
|||||||
/* controls gc off feature for pci gpu */
|
/* controls gc off feature for pci gpu */
|
||||||
bool can_pci_gc_off;
|
bool can_pci_gc_off;
|
||||||
|
|
||||||
|
#ifdef CONFIG_NVGPU_STATIC_POWERGATE
|
||||||
/* Should be populated at probe. */
|
/* Should be populated at probe. */
|
||||||
bool can_tpc_pg;
|
bool can_tpc_pg;
|
||||||
|
|
||||||
@@ -89,7 +90,7 @@ struct gk20a_platform {
|
|||||||
|
|
||||||
/* Should be populated at probe. */
|
/* Should be populated at probe. */
|
||||||
bool can_gpc_pg;
|
bool can_gpc_pg;
|
||||||
|
#endif
|
||||||
/* Should be populated at probe. */
|
/* Should be populated at probe. */
|
||||||
bool can_elpg_init;
|
bool can_elpg_init;
|
||||||
|
|
||||||
@@ -118,12 +119,14 @@ struct gk20a_platform {
|
|||||||
/* Reset control for device */
|
/* Reset control for device */
|
||||||
struct reset_control *reset_control;
|
struct reset_control *reset_control;
|
||||||
#endif
|
#endif
|
||||||
/* valid TPC-MASK */
|
|
||||||
u32 valid_tpc_mask[MAX_TPC_PG_CONFIGS];
|
|
||||||
|
|
||||||
/* Valid GPC and FBP mask */
|
#ifdef CONFIG_NVGPU_STATIC_POWERGATE
|
||||||
u32 valid_gpc_fbp_fs_mask[MAX_GPC_FBP_FS_CONFIGS];
|
/* valid TPC-PG MASK */
|
||||||
|
u32 valid_tpc_pg_mask[MAX_PG_TPC_CONFIGS];
|
||||||
|
|
||||||
|
/* Valid GPC-PG and FBP-PG mask */
|
||||||
|
u32 valid_gpc_fbp_pg_mask[MAX_PG_GPC_FBP_CONFIGS];
|
||||||
|
#endif
|
||||||
/* Delay before rail gated */
|
/* Delay before rail gated */
|
||||||
int railgate_delay_init;
|
int railgate_delay_init;
|
||||||
|
|
||||||
@@ -244,15 +247,16 @@ struct gk20a_platform {
|
|||||||
/* Pre callback is called before frequency change */
|
/* Pre callback is called before frequency change */
|
||||||
void (*prescale)(struct device *dev);
|
void (*prescale)(struct device *dev);
|
||||||
|
|
||||||
|
#ifdef CONFIG_NVGPU_STATIC_POWERGATE
|
||||||
/* Set TPC_PG_MASK during probe */
|
/* Set TPC_PG_MASK during probe */
|
||||||
void (*set_tpc_pg_mask)(struct device *dev, u32 tpc_pg_mask);
|
int (*set_tpc_pg_mask)(struct device *dev, u32 dt_tpc_pg_mask);
|
||||||
|
|
||||||
/* Set GPC_MASK during probe */
|
/* Set GPC_PG_MASK during probe */
|
||||||
void (*set_gpc_mask)(struct device *dev, u32 gpc_mask);
|
int (*set_gpc_pg_mask)(struct device *dev, u32 dt_gpc_pg_mask);
|
||||||
|
|
||||||
/* Set FBP_MASK during probe */
|
|
||||||
void (*set_fbp_mask)(struct device *dev, u32 fbp_mask);
|
|
||||||
|
|
||||||
|
/* Set FBP_PG_MASK during probe */
|
||||||
|
int (*set_fbp_pg_mask)(struct device *dev, u32 dt_fbp_pg_mask);
|
||||||
|
#endif
|
||||||
/* 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;
|
||||||
|
|||||||
@@ -207,13 +207,14 @@ static int gv11b_tegra_suspend(struct device *dev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool is_tpc_mask_valid(struct gk20a_platform *platform, u32 tpc_pg_mask)
|
static bool gv11b_tegra_is_tpc_mask_valid(struct gk20a_platform *platform,
|
||||||
|
u32 dt_tpc_pg_mask)
|
||||||
{
|
{
|
||||||
u32 i;
|
u32 i;
|
||||||
bool valid = false;
|
bool valid = false;
|
||||||
|
|
||||||
for (i = 0; i < MAX_TPC_PG_CONFIGS; i++) {
|
for (i = 0U; i < MAX_PG_TPC_CONFIGS; i++) {
|
||||||
if (tpc_pg_mask == platform->valid_tpc_mask[i]) {
|
if (dt_tpc_pg_mask == platform->valid_tpc_pg_mask[i]) {
|
||||||
valid = true;
|
valid = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -221,13 +222,17 @@ static bool is_tpc_mask_valid(struct gk20a_platform *platform, u32 tpc_pg_mask)
|
|||||||
return valid;
|
return valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gv11b_tegra_set_tpc_pg_mask(struct device *dev, u32 tpc_pg_mask)
|
static int gv11b_tegra_set_tpc_pg_mask(struct device *dev, u32 dt_tpc_pg_mask)
|
||||||
{
|
{
|
||||||
struct gk20a_platform *platform = gk20a_get_platform(dev);
|
struct gk20a_platform *platform = gk20a_get_platform(dev);
|
||||||
struct gk20a *g = get_gk20a(dev);
|
struct gk20a *g = get_gk20a(dev);
|
||||||
|
|
||||||
if (is_tpc_mask_valid(platform, tpc_pg_mask)) {
|
if (gv11b_tegra_is_tpc_mask_valid(platform, dt_tpc_pg_mask)) {
|
||||||
g->tpc_pg_mask = tpc_pg_mask;
|
g->tpc_pg_mask[PG_GPC0] = dt_tpc_pg_mask;
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
nvgpu_err(g, "Invalid TPC-PG mask");
|
||||||
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -245,21 +250,22 @@ struct gk20a_platform gv11b_tegra_platform = {
|
|||||||
.late_probe = gv11b_tegra_late_probe,
|
.late_probe = gv11b_tegra_late_probe,
|
||||||
.remove = gv11b_tegra_remove,
|
.remove = gv11b_tegra_remove,
|
||||||
.railgate_delay_init = 500,
|
.railgate_delay_init = 500,
|
||||||
.can_railgate_init = true,
|
|
||||||
|
|
||||||
.can_tpc_pg = true,
|
.can_railgate_init = true,
|
||||||
.valid_tpc_mask[0] = 0x0,
|
#ifdef CONFIG_NVGPU_STATIC_POWERGATE
|
||||||
.valid_tpc_mask[1] = 0x1,
|
.can_tpc_pg = true,
|
||||||
.valid_tpc_mask[2] = 0x2,
|
.valid_tpc_pg_mask[0] = 0x0,
|
||||||
.valid_tpc_mask[3] = 0x4,
|
.valid_tpc_pg_mask[1] = 0x1,
|
||||||
.valid_tpc_mask[4] = 0x8,
|
.valid_tpc_pg_mask[2] = 0x2,
|
||||||
.valid_tpc_mask[5] = 0x5,
|
.valid_tpc_pg_mask[3] = 0x4,
|
||||||
.valid_tpc_mask[6] = 0x6,
|
.valid_tpc_pg_mask[4] = 0x8,
|
||||||
.valid_tpc_mask[7] = 0x9,
|
.valid_tpc_pg_mask[5] = 0x5,
|
||||||
.valid_tpc_mask[8] = 0xa,
|
.valid_tpc_pg_mask[6] = 0x6,
|
||||||
|
.valid_tpc_pg_mask[7] = 0x9,
|
||||||
|
.valid_tpc_pg_mask[8] = 0xa,
|
||||||
|
|
||||||
.set_tpc_pg_mask = gv11b_tegra_set_tpc_pg_mask,
|
.set_tpc_pg_mask = gv11b_tegra_set_tpc_pg_mask,
|
||||||
|
#endif
|
||||||
.can_slcg = true,
|
.can_slcg = true,
|
||||||
.can_blcg = true,
|
.can_blcg = true,
|
||||||
.can_elcg = true,
|
.can_elcg = true,
|
||||||
|
|||||||
@@ -836,14 +836,6 @@ static ssize_t force_idle_read(struct device *dev,
|
|||||||
static DEVICE_ATTR(force_idle, ROOTRW, force_idle_read, force_idle_store);
|
static DEVICE_ATTR(force_idle, ROOTRW, force_idle_read, force_idle_store);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static ssize_t tpc_pg_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->tpc_pg_mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t gpc_fs_mask_show(struct device *dev,
|
static ssize_t gpc_fs_mask_show(struct device *dev,
|
||||||
struct device_attribute *attr, char *buf)
|
struct device_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
@@ -886,13 +878,14 @@ static ssize_t fbp_fs_mask_show(struct device *dev,
|
|||||||
|
|
||||||
static DEVICE_ATTR_RO(fbp_fs_mask);
|
static DEVICE_ATTR_RO(fbp_fs_mask);
|
||||||
|
|
||||||
|
#ifdef CONFIG_NVGPU_STATIC_POWERGATE
|
||||||
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;
|
||||||
bool valid = false;
|
bool valid = false;
|
||||||
|
|
||||||
for (i = 0; i < MAX_TPC_PG_CONFIGS; i++) {
|
for (i = 0U; i < MAX_PG_TPC_CONFIGS; i++) {
|
||||||
if (tpc_mask == g->valid_tpc_mask[i]) {
|
if (tpc_mask == g->valid_tpc_pg_mask[i]) {
|
||||||
valid = true;
|
valid = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -900,6 +893,15 @@ static bool is_tpc_mask_valid(struct gk20a *g, u32 tpc_mask)
|
|||||||
return valid;
|
return valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ssize_t tpc_pg_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->tpc_pg_mask[PG_GPC0]);
|
||||||
|
}
|
||||||
|
|
||||||
static ssize_t tpc_pg_mask_store(struct device *dev,
|
static ssize_t tpc_pg_mask_store(struct device *dev,
|
||||||
struct device_attribute *attr, const char *buf, size_t count)
|
struct device_attribute *attr, const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
@@ -915,7 +917,7 @@ static ssize_t tpc_pg_mask_store(struct device *dev,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (val == g->tpc_pg_mask) {
|
if (val == g->tpc_pg_mask[PG_GPC0]) {
|
||||||
nvgpu_info(g, "no value change, same mask already set");
|
nvgpu_info(g, "no value change, same mask already set");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
@@ -935,7 +937,7 @@ static ssize_t tpc_pg_mask_store(struct device *dev,
|
|||||||
* the possible valid TPC configurations.
|
* the possible valid TPC configurations.
|
||||||
*/
|
*/
|
||||||
if (is_tpc_mask_valid(g, (u32)val)) {
|
if (is_tpc_mask_valid(g, (u32)val)) {
|
||||||
g->tpc_pg_mask = val;
|
g->tpc_pg_mask[PG_GPC0] = val;
|
||||||
} else {
|
} else {
|
||||||
nvgpu_err(g, "TPC-PG mask is invalid");
|
nvgpu_err(g, "TPC-PG mask is invalid");
|
||||||
nvgpu_mutex_release(&g->static_pg_lock);
|
nvgpu_mutex_release(&g->static_pg_lock);
|
||||||
@@ -946,6 +948,7 @@ exit:
|
|||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static DEVICE_ATTR(tpc_pg_mask, ROOTRW, tpc_pg_mask_read, tpc_pg_mask_store);
|
static DEVICE_ATTR(tpc_pg_mask, ROOTRW, tpc_pg_mask_read, tpc_pg_mask_store);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user