mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-24 10:34:43 +03:00
gpu: nvgpu: Use TPC_PG_MASK to powergate the TPC
- In GV11B, read fuse_status_opt_tpc_gpc register to read which TPCs are floorswept. - The driver will also read sysfs node: tpc_pg_mask - Based on these two values "can_tpc_powergate" will be set to true or false and mask will be used to write to fuse_ctrl_opt_tpc_gpc register to powergate the TPC. - can_tpc_powergate = true indicates that the mask value sent from userspace is valid and can be used to power gate the desired TPC - can_tpc_powergate = false indicates that the mask value sent from userspace is not valid and cannot be used to power gate the desired TPC. Bug 200532639 Change-Id: Ib0806e4c96305a13b3574e8063ad8e16770aa7cd Signed-off-by: Divya Singhatwaria <dsinghatwari@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/2159219 Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
committed by
mobile promotions
parent
47f6bc0c2e
commit
ae175e45ed
@@ -1200,7 +1200,8 @@ static int nvgpu_read_fuse_overrides(struct gk20a *g)
|
||||
break;
|
||||
case GV11B_FUSE_OPT_TPC_DISABLE:
|
||||
if (platform->set_tpc_pg_mask != NULL)
|
||||
platform->set_tpc_pg_mask(dev_from_gk20a(g), value);
|
||||
platform->set_tpc_pg_mask(dev_from_gk20a(g),
|
||||
value);
|
||||
break;
|
||||
default:
|
||||
nvgpu_err(g, "ignore unknown fuse override %08x", fuse);
|
||||
|
||||
@@ -196,8 +196,8 @@ struct gk20a_platform {
|
||||
/* Pre callback is called before frequency change */
|
||||
void (*prescale)(struct device *dev);
|
||||
|
||||
/* Set TPC_PG during probe */
|
||||
void (*set_tpc_pg_mask)(struct device *dev, u32 tpc_mask);
|
||||
/* Set TPC_PG_MASK during probe */
|
||||
void (*set_tpc_pg_mask)(struct device *dev, u32 tpc_pg_mask);
|
||||
|
||||
/* Devfreq governor name. If scaling is enabled, we request
|
||||
* this governor to be used in scaling */
|
||||
|
||||
@@ -218,26 +218,29 @@ static int gv11b_tegra_suspend(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool is_tpc_mask_valid(struct gk20a_platform *platform, u32 tpc_mask)
|
||||
static bool is_tpc_mask_valid(struct gk20a_platform *platform, u32 tpc_pg_mask)
|
||||
{
|
||||
u32 i;
|
||||
bool valid = false;
|
||||
|
||||
for (i = 0; i < MAX_TPC_PG_CONFIGS; i++) {
|
||||
if (tpc_mask == platform->valid_tpc_mask[i])
|
||||
if (tpc_pg_mask == platform->valid_tpc_mask[i]) {
|
||||
valid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
static void gv11b_tegra_set_tpc_pg_mask(struct device *dev, u32 tpc_mask)
|
||||
static void gv11b_tegra_set_tpc_pg_mask(struct device *dev, u32 tpc_pg_mask)
|
||||
{
|
||||
struct gk20a_platform *platform = gk20a_get_platform(dev);
|
||||
struct gk20a *g = get_gk20a(dev);
|
||||
|
||||
if (is_tpc_mask_valid(platform, tpc_mask)) {
|
||||
g->tpc_pg_mask = tpc_mask;
|
||||
if (is_tpc_mask_valid(platform, tpc_pg_mask)) {
|
||||
g->tpc_pg_mask = tpc_pg_mask;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct gk20a_platform gv11b_tegra_platform = {
|
||||
@@ -257,9 +260,15 @@ struct gk20a_platform gv11b_tegra_platform = {
|
||||
.can_tpc_powergate = true,
|
||||
.valid_tpc_mask[0] = 0x0,
|
||||
.valid_tpc_mask[1] = 0x1,
|
||||
.valid_tpc_mask[2] = 0x5,
|
||||
.valid_tpc_mask[2] = 0x2,
|
||||
.valid_tpc_mask[3] = 0x4,
|
||||
.valid_tpc_mask[4] = 0x8,
|
||||
.valid_tpc_mask[5] = 0x5,
|
||||
.valid_tpc_mask[6] = 0x6,
|
||||
.valid_tpc_mask[7] = 0x9,
|
||||
.valid_tpc_mask[8] = 0xa,
|
||||
|
||||
.set_tpc_pg_mask = gv11b_tegra_set_tpc_pg_mask,
|
||||
.set_tpc_pg_mask = gv11b_tegra_set_tpc_pg_mask,
|
||||
|
||||
.can_slcg = true,
|
||||
.can_blcg = true,
|
||||
|
||||
@@ -788,26 +788,28 @@ static ssize_t force_idle_read(struct device *dev,
|
||||
static DEVICE_ATTR(force_idle, ROOTRW, force_idle_read, force_idle_store);
|
||||
#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, PAGE_SIZE, "%d\n", g->tpc_pg_mask);
|
||||
}
|
||||
|
||||
static bool is_tpc_mask_valid(struct gk20a *g, u32 tpc_mask)
|
||||
{
|
||||
u32 i;
|
||||
bool valid = false;
|
||||
|
||||
for (i = 0; i < MAX_TPC_PG_CONFIGS; i++) {
|
||||
if (tpc_mask == g->valid_tpc_mask[i])
|
||||
if (tpc_mask == g->valid_tpc_mask[i]) {
|
||||
valid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
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, PAGE_SIZE, "%d\n", g->tpc_pg_mask);
|
||||
}
|
||||
|
||||
static ssize_t tpc_pg_mask_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
@@ -817,11 +819,6 @@ static ssize_t tpc_pg_mask_store(struct device *dev,
|
||||
|
||||
nvgpu_mutex_acquire(&g->tpc_pg_lock);
|
||||
|
||||
if (!g->can_tpc_powergate) {
|
||||
nvgpu_info(g, "TPC-PG not enabled for the platform");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (kstrtoul(buf, 10, &val) < 0) {
|
||||
nvgpu_err(g, "invalid value");
|
||||
nvgpu_mutex_release(&g->tpc_pg_lock);
|
||||
@@ -839,6 +836,9 @@ static ssize_t tpc_pg_mask_store(struct device *dev,
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* checking that the value from userspace is within
|
||||
* the possible valid TPC configurations.
|
||||
*/
|
||||
if (is_tpc_mask_valid(g, (u32)val)) {
|
||||
g->tpc_pg_mask = val;
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user