// SPDX-License-Identifier: GPL-2.0-or-later /* * Platform energy and frequency attributes driver * * This driver creates a sys file at /sys/firmware/papr/ which encapsulates a * directory structure containing files in keyword - value pairs that specify * energy and frequency configuration of the system. * * The format of exposing the sysfs information is as follows: * /sys/firmware/papr/energy_scale_info/ * |-- <id>/ * |-- desc * |-- value * |-- value_desc (if exists) * |-- <id>/ * |-- desc * |-- value * |-- value_desc (if exists) * * Copyright 2022 IBM Corp.
*/
/* * Flag attributes to fetch either all or one attribute from the HCALL * flag = BE(0) => fetch all attributes with firstAttributeId = 0 * flag = BE(1) => fetch a single attribute with firstAttributeId = id
*/ #define ESI_FLAGS_ALL 0 #define ESI_FLAGS_SINGLE (1ull << 63)
/* * Energy modes can change dynamically hence making a new hcall each time the * information needs to be retrieved
*/ staticint papr_get_attr(u64 id, struct energy_scale_attribute *esi)
{ int esi_buf_size = ESI_HDR_SIZE + (CURR_MAX_ESI_ATTRS * ESI_ATTR_SIZE); int ret, max_esi_attrs = CURR_MAX_ESI_ATTRS; struct energy_scale_attribute *curr_esi; struct h_energy_scale_info_hdr *hdr; char *buf;
buf = kmalloc(esi_buf_size, GFP_KERNEL); if (buf == NULL) return -ENOMEM;
retry:
ret = plpar_hcall_norets(H_GET_ENERGY_SCALE_INFO, ESI_FLAGS_SINGLE,
id, virt_to_phys(buf),
esi_buf_size);
/* * If the hcall fails with not enough memory for either the * header or data, attempt to allocate more
*/ if (ret == H_PARTIAL || ret == H_P4) { char *temp_buf;
/* * Extract and export the value description in string format of the energy * scale attributes
*/ static ssize_t val_desc_show(struct kobject *kobj, struct kobj_attribute *kobj_attr, char *buf)
{ struct papr_attr *pattr = container_of(kobj_attr, struct papr_attr,
kobj_attr); struct energy_scale_attribute esi; int ret;
ret = papr_get_attr(pattr->id, &esi); if (ret) return ret;
for (i = 0; i < KOBJ_MAX_ATTRS; i++) { if (!strcmp(ops_info[i].attr_name, "value_desc") &&
!show_val_desc) { continue;
}
add_attr(id, i, &pg->pgattrs[i]);
pg->pg.attrs[i] = &pg->pgattrs[i].kobj_attr.attr;
}
return sysfs_create_group(esi_kobj, &pg->pg);
}
staticint __init papr_init(void)
{ int esi_buf_size = ESI_HDR_SIZE + (CURR_MAX_ESI_ATTRS * ESI_ATTR_SIZE); int ret, idx, i, max_esi_attrs = CURR_MAX_ESI_ATTRS; struct h_energy_scale_info_hdr *esi_hdr; struct energy_scale_attribute *esi_attrs;
uint64_t num_attrs; char *esi_buf;
if (!firmware_has_feature(FW_FEATURE_LPAR) ||
!firmware_has_feature(FW_FEATURE_ENERGY_SCALE_INFO)) { return -ENXIO;
}
esi_buf = kmalloc(esi_buf_size, GFP_KERNEL); if (esi_buf == NULL) return -ENOMEM; /* * hcall( * uint64 H_GET_ENERGY_SCALE_INFO, // Get energy scale info * uint64 flags, // Per the flag request * uint64 firstAttributeId, // The attribute id * uint64 bufferAddress, // Guest physical address of the output buffer * uint64 bufferSize); // The size in bytes of the output buffer
*/
retry:
ret = plpar_hcall_norets(H_GET_ENERGY_SCALE_INFO, ESI_FLAGS_ALL, 0,
virt_to_phys(esi_buf), esi_buf_size);
/* * If the hcall fails with not enough memory for either the * header or data, attempt to allocate more
*/ if (ret == H_PARTIAL || ret == H_P4) { char *temp_esi_buf;
/* Do not add the value desc attr if it does not exist */ if (strnlen(esi_attrs[idx].value_desc, sizeof(esi_attrs[idx].value_desc)) == 0)
show_val_desc = false;
if (add_attr_group(be64_to_cpu(esi_attrs[idx].id),
&papr_groups[idx],
show_val_desc)) {
pr_warn("Failed to create papr attribute group %s\n",
papr_groups[idx].pg.name);
idx = num_attrs; goto out_pgattrs;
}
}
kfree(esi_buf); return 0;
out_pgattrs: for (i = 0; i < idx ; i++) {
kfree(papr_groups[i].pg.attrs);
kfree(papr_groups[i].pg.name);
}
kobject_put(esi_kobj);
out_kobj:
kobject_put(papr_kobj);
out_papr_groups:
kfree(papr_groups);
out_free_esi_buf:
kfree(esi_buf);
return -ENOMEM;
}
machine_device_initcall(pseries, papr_init);
Messung V0.5
¤ Dauer der Verarbeitung: 0.15 Sekunden
(vorverarbeitet)
¤
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.