/* * export_imc_mode_and_cmd: Create a debugfs interface * for imc_cmd and imc_mode * for each node in the system. * imc_mode and imc_cmd can be changed by echo into * this interface.
*/ staticvoid export_imc_mode_and_cmd(struct device_node *node, struct imc_pmu *pmu_ptr)
{ static u64 loc, *imc_mode_addr, *imc_cmd_addr; char mode[16], cmd[16];
u32 cb_offset; struct imc_mem_info *ptr = pmu_ptr->mem_info;
/* * imc_get_mem_addr_nest: Function to get nest counter memory region * for each chip
*/ staticint imc_get_mem_addr_nest(struct device_node *node, struct imc_pmu *pmu_ptr,
u32 offset)
{ int nr_chips = 0, i;
u64 *base_addr_arr, baddr;
u32 *chipid_arr;
nr_chips = of_property_count_u32_elems(node, "chip-id"); if (nr_chips <= 0) return -ENODEV;
base_addr_arr = kcalloc(nr_chips, sizeof(*base_addr_arr), GFP_KERNEL); if (!base_addr_arr) return -ENOMEM;
/* * imc_pmu_create : Takes the parent device which is the pmu unit, pmu_index * and domain as the inputs. * Allocates memory for the struct imc_pmu, sets up its domain, size and offsets
*/ staticstruct imc_pmu *imc_pmu_create(struct device_node *parent, int pmu_index, int domain)
{ int ret = 0; struct imc_pmu *pmu_ptr;
u32 offset;
/* Return for unknown domain */ if (domain < 0) return NULL;
/* memory for pmu */
pmu_ptr = kzalloc(sizeof(*pmu_ptr), GFP_KERNEL); if (!pmu_ptr) return NULL;
/* Set the domain */
pmu_ptr->domain = domain;
ret = of_property_read_u32(parent, "size", &pmu_ptr->counter_mem_size); if (ret) goto free_pmu;
if (!of_property_read_u32(parent, "offset", &offset)) { if (imc_get_mem_addr_nest(parent, pmu_ptr, offset)) goto free_pmu;
}
/* Function to register IMC pmu */
ret = init_imc_pmu(parent, pmu_ptr, pmu_index); if (ret) {
pr_err("IMC PMU %s Register failed\n", pmu_ptr->pmu.name);
kfree(pmu_ptr->pmu.name); if (pmu_ptr->domain == IMC_DOMAIN_NEST)
kfree(pmu_ptr->mem_info);
kfree(pmu_ptr); return NULL;
}
return pmu_ptr;
free_pmu:
kfree(pmu_ptr); return NULL;
}
staticvoid disable_nest_pmu_counters(void)
{ int nid, cpu; conststruct cpumask *l_cpumask;
cpus_read_lock();
for_each_node_with_cpus(nid) {
l_cpumask = cpumask_of_node(nid);
cpu = cpumask_first_and(l_cpumask, cpu_online_mask); if (cpu >= nr_cpu_ids) continue;
opal_imc_counters_stop(OPAL_IMC_COUNTERS_NEST,
get_hard_smp_processor_id(cpu));
}
cpus_read_unlock();
}
staticvoid disable_core_pmu_counters(void)
{ int cpu, rc;
cpus_read_lock(); /* Disable the IMC Core functions */
for_each_online_cpu(cpu) { if (cpu_first_thread_sibling(cpu) != cpu) continue;
rc = opal_imc_counters_stop(OPAL_IMC_COUNTERS_CORE,
get_hard_smp_processor_id(cpu)); if (rc)
pr_err("%s: Failed to stop Core (cpu = %d)\n",
__func__, cpu);
}
cpus_read_unlock();
}
/* * Check whether this is kdump kernel. If yes, force the engines to * stop and return.
*/ if (is_kdump_kernel()) {
disable_nest_pmu_counters();
disable_core_pmu_counters(); return -ENODEV;
}
for_each_compatible_node(imc_dev, NULL, IMC_DTB_UNIT_COMPAT) {
pmu = NULL; if (of_property_read_u32(imc_dev, "type", &type)) {
pr_warn("IMC Device without type property\n"); continue;
}
switch (type) { case IMC_TYPE_CHIP:
domain = IMC_DOMAIN_NEST; break; case IMC_TYPE_CORE:
domain =IMC_DOMAIN_CORE; break; case IMC_TYPE_THREAD:
domain = IMC_DOMAIN_THREAD; break; case IMC_TYPE_TRACE:
domain = IMC_DOMAIN_TRACE; break; default:
pr_warn("IMC Unknown Device type \n");
domain = -1; break;
}
pmu = imc_pmu_create(imc_dev, pmu_count, domain); if (pmu != NULL) { if (domain == IMC_DOMAIN_NEST) { if (!imc_debugfs_parent)
export_imc_mode_and_cmd(imc_dev, pmu);
pmu_count++;
} if (domain == IMC_DOMAIN_CORE)
core_imc_reg = true; if (domain == IMC_DOMAIN_THREAD)
thread_imc_reg = true;
}
}
/* If core imc is not registered, unregister thread-imc */ if (!core_imc_reg && thread_imc_reg)
unregister_thread_imc();
return 0;
}
staticvoid opal_imc_counters_shutdown(struct platform_device *pdev)
{ /* * Function only stops the engines which is bare minimum. * TODO: Need to handle proper memory cleanup and pmu * unregister.
*/
disable_nest_pmu_counters();
disable_core_pmu_counters();
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.