Skip to content

Commit

Permalink
fast-reboot: occ: Remove 'freq-domain-mask' from fast-reboot path
Browse files Browse the repository at this point in the history
OCC can change the pstate table at runtime to modify pstate limits or
for characterization purpose. These changes are reflected by re-parsing
the pstate table during fast-reboot to update the device-tree. Only
relevant pstate DT properties are deleted and newly added during
fast-reboot. The device-tree properties like 'freq-domain-mask' and
'domain-runs-at' are currently hard-coded and need not be updated
during fast-reboot. So this patch removes them from the fast-reboot path.

This patch fixes the below crash:
[  270.313998453,5] OCC: All Chip Rdy after 0 ms
[  270.314148918,3] Duplicate property "freq-domain-mask" in node /ibm,opal/power-mgt
[  270.314208553,0] Aborting!
CPU 083c Backtrace:
 S: 0000000035de3a20 R: 000000003001b480   ._abort+0x4c
 S: 0000000035de3aa0 R: 0000000030028704   .new_property+0xd8
 S: 0000000035de3b30 R: 0000000030028964   .__dt_add_property_cells+0x30
 S: 0000000035de3bd0 R: 0000000030042980   .occ_pstates_init+0x7c8
 S: 0000000035de3d90 R: 00000000300145f4   .load_and_boot_kernel+0x980
 S: 0000000035de3e70 R: 00000000300276b4   .fast_reboot_entry+0x37c
 S: 0000000035de3f00 R: 0000000030002ac4   reset_fast_reboot_wakeup+0x40

Fixes: b821f8c("power-mgmt : occ : Add 'freq-domain-mask' DT property")
Reported-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
Signed-off-by: Shilpasri G Bhat <shilpa.bhat@linux.vnet.ibm.com>
Tested-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
Signed-off-by: Stewart Smith <stewart@linux.ibm.com>
  • Loading branch information
shilpasri authored and stewartsmith committed Mar 15, 2019
1 parent 9989114 commit 27e4943
Showing 1 changed file with 42 additions and 43 deletions.
85 changes: 42 additions & 43 deletions hw/occ.c
Original file line number Diff line number Diff line change
Expand Up @@ -491,27 +491,18 @@ static void parse_vid(struct occ_pstate_table *occ_data,

/* Add device tree properties to describe pstates states */
/* Return nominal pstate to set in each core */
static bool add_cpu_pstate_properties(int *pstate_nom)
static bool add_cpu_pstate_properties(struct dt_node *power_mgt,
int *pstate_nom)
{
struct proc_chip *chip;
uint64_t occ_data_area;
struct occ_pstate_table *occ_data;
struct dt_node *power_mgt;
/* Arrays for device tree */
u32 *dt_id, *dt_freq;
int pmax, pmin, pnom;
u8 nr_pstates;
bool ultra_turbo_supported;
int i, major, minor;
u8 domain_runs_at;
u32 freq_domain_mask;

/* TODO Firmware plumbing required so as to have two modes to set
* PMCR based on max in domain or most recently used. As of today,
* it is always max in domain for P9.
*/
domain_runs_at = 0;
freq_domain_mask = 0;

prlog(PR_DEBUG, "OCC: CPU pstate state device tree init\n");

Expand Down Expand Up @@ -654,18 +645,6 @@ static bool add_cpu_pstate_properties(int *pstate_nom)
return false;
}

power_mgt = dt_find_by_path(dt_root, "/ibm,opal/power-mgt");
if (!power_mgt) {
/**
* @fwts-label OCCDTNodeNotFound
* @fwts-advice Device tree node /ibm,opal/power-mgt not
* found. OPAL didn't add pstate information to device tree.
* Probably a firmware bug.
*/
prlog(PR_ERR, "OCC: dt node /ibm,opal/power-mgt not found\n");
return false;
}

dt_id = malloc(nr_pstates * sizeof(u32));
assert(dt_id);
dt_freq = malloc(nr_pstates * sizeof(u32));
Expand All @@ -684,14 +663,6 @@ static bool add_cpu_pstate_properties(int *pstate_nom)
return false;
}

if (proc_gen == proc_gen_p8) {
freq_domain_mask = P8_PIR_CORE_MASK;
domain_runs_at = FREQ_MOST_RECENTLY_SET;
} else if (proc_gen == proc_gen_p9) {
freq_domain_mask = P9_PIR_QUAD_MASK;
domain_runs_at = FREQ_MAX_IN_DOMAIN;
}

/* Add the device-tree entries */
dt_add_property(power_mgt, "ibm,pstate-ids", dt_id,
nr_pstates * sizeof(u32));
Expand All @@ -700,8 +671,6 @@ static bool add_cpu_pstate_properties(int *pstate_nom)
dt_add_property_cells(power_mgt, "ibm,pstate-min", pmin);
dt_add_property_cells(power_mgt, "ibm,pstate-nominal", pnom);
dt_add_property_cells(power_mgt, "ibm,pstate-max", pmax);
dt_add_property_cells(power_mgt, "freq-domain-mask", freq_domain_mask);
dt_add_property_cells(power_mgt, "domain-runs-at", domain_runs_at);

free(dt_freq);
free(dt_id);
Expand Down Expand Up @@ -1752,15 +1721,31 @@ void occ_pstates_init(void)
{
struct proc_chip *chip;
struct cpu_thread *c;
struct dt_node *power_mgt;
int pstate_nom;
u32 freq_domain_mask;
u8 domain_runs_at;
static bool occ_pstates_initialized;

/* OCC is supported in P8 and P9 */
if (proc_gen < proc_gen_p8)
return;

power_mgt = dt_find_by_path(dt_root, "/ibm,opal/power-mgt");
if (!power_mgt) {
/**
* @fwts-label OCCDTNodeNotFound
* @fwts-advice Device tree node /ibm,opal/power-mgt not
* found. OPAL didn't add pstate information to device tree.
* Probably a firmware bug.
*/
prlog(PR_ERR, "OCC: dt node /ibm,opal/power-mgt not found\n");
return;
}

/* Handle fast reboots */
if (occ_pstates_initialized) {
struct dt_node *power_mgt, *child;
struct dt_node *child;
int i;
const char *props[] = {
"ibm,pstate-core-max",
Expand All @@ -1775,15 +1760,12 @@ void occ_pstates_init(void)
"#size-cells",
};

power_mgt = dt_find_by_path(dt_root, "/ibm,opal/power-mgt");
if (power_mgt) {
for (i = 0; i < ARRAY_SIZE(props); i++)
dt_check_del_prop(power_mgt, props[i]);
for (i = 0; i < ARRAY_SIZE(props); i++)
dt_check_del_prop(power_mgt, props[i]);

dt_for_each_child(power_mgt, child)
if (!strncmp(child->name, "occ", 3))
dt_free(child);
}
dt_for_each_child(power_mgt, child)
if (!strncmp(child->name, "occ", 3))
dt_free(child);
}

switch (proc_gen) {
Expand Down Expand Up @@ -1816,7 +1798,7 @@ void occ_pstates_init(void)
* Check boundary conditions and add device tree nodes
* and return nominal pstate to set for the core
*/
if (!add_cpu_pstate_properties(&pstate_nom)) {
if (!add_cpu_pstate_properties(power_mgt, &pstate_nom)) {
log_simple_error(&e_info(OPAL_RC_OCC_PSTATE_INIT),
"Skiping core cpufreq init due to OCC error\n");
} else if (proc_gen == proc_gen_p8) {
Expand All @@ -1840,6 +1822,23 @@ void occ_pstates_init(void)

/* Init OPAL-OCC command-response interface */
occ_cmd_interface_init();

/* TODO Firmware plumbing required so as to have two modes to set
* PMCR based on max in domain or most recently used. As of today,
* it is always max in domain for P9.
*/
domain_runs_at = 0;
freq_domain_mask = 0;
if (proc_gen == proc_gen_p8) {
freq_domain_mask = P8_PIR_CORE_MASK;
domain_runs_at = FREQ_MOST_RECENTLY_SET;
} else if (proc_gen == proc_gen_p9) {
freq_domain_mask = P9_PIR_QUAD_MASK;
domain_runs_at = FREQ_MAX_IN_DOMAIN;
}

dt_add_property_cells(power_mgt, "freq-domain-mask", freq_domain_mask);
dt_add_property_cells(power_mgt, "domain-runs-at", domain_runs_at);
}

struct occ_load_req {
Expand Down

0 comments on commit 27e4943

Please sign in to comment.