/** *acpi_parse_art-ParseActiveRelationshipTable_ART * *@handle:ACPIhandleofthedevicecontains_ART *@art_count:thenumberofvalidentriesresultedfromparsing_ART *@artp:pointertopointerofarrayofartentriesinparsingresult *@create_dev:whethertocreateplatformdevicesfortargetandsource *
*/ int acpi_parse_art(acpi_handle handle, int *art_count, struct art **artp, bool create_dev)
{
acpi_status status; int result = 0; int i; int nr_bad_entries = 0; struct art *arts; union acpi_object *p; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; struct acpi_buffer element = { 0, NULL }; struct acpi_buffer art_format = { sizeof("RRNNNNNNNNNNN"), "RRNNNNNNNNNNN" };
status = acpi_evaluate_object(handle, "_ART", NULL, &buffer); if (ACPI_FAILURE(status)) return -ENODEV;
p = buffer.pointer; if (!p || (p->type != ACPI_TYPE_PACKAGE)) {
pr_err("Invalid _ART data\n");
result = -EFAULT; goto end;
}
/* ignore p->package.elements[0], as this is _ART Revision field */
*art_count = p->package.count - 1;
arts = kcalloc(*art_count, sizeof(struct art), GFP_KERNEL); if (!arts) {
result = -ENOMEM; goto end;
}
for (i = 0; i < *art_count; i++) { struct art *art = &arts[i - nr_bad_entries];
res = acpi_fetch_acpi_dev(psvt->source); if (!res) {
nr_bad_entries++;
pr_info("Failed to get source ACPI device\n"); continue;
}
res = acpi_fetch_acpi_dev(psvt->target); if (!res) {
nr_bad_entries++;
pr_info("Failed to get target ACPI device\n"); continue;
}
}
/* don't count bad entries */
*psvt_count -= nr_bad_entries;
if (!*psvt_count) {
result = -EFAULT;
kfree(psvts); goto end;
}
*psvtp = psvts;
return0;
end:
kfree(buffer.pointer); return result;
}
/* get device name from acpi handle */ staticvoid get_single_name(acpi_handle handle, char *name)
{ struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER};
if (ACPI_FAILURE(acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer)))
pr_warn("Failed to get device name from acpi handle\n"); else {
memcpy(name, buffer.pointer, ACPI_NAMESEG_SIZE);
kfree(buffer.pointer);
}
}
staticint fill_art(char __user *ubuf)
{ int i; int ret; int count; int art_len; struct art *arts = NULL; union art_object *art_user;
ret = acpi_parse_art(acpi_thermal_rel_handle, &count, &arts, false); if (ret) goto free_art;
art_len = count * sizeof(union art_object);
art_user = kzalloc(art_len, GFP_KERNEL); if (!art_user) {
ret = -ENOMEM; goto free_art;
} /* now fill in user art data */ for (i = 0; i < count; i++) { /* userspace art needs device name instead of acpi reference */
get_single_name(arts[i].source, art_user[i].source_device);
get_single_name(arts[i].target, art_user[i].target_device); /* copy the rest int data in addition to source and target */
BUILD_BUG_ON(sizeof(art_user[i].data) != sizeof(u64) * (ACPI_NR_ART_ELEMENTS - 2));
memcpy(&art_user[i].data, &arts[i].data, sizeof(art_user[i].data));
}
if (copy_to_user(ubuf, art_user, art_len))
ret = -EFAULT;
kfree(art_user);
free_art:
kfree(arts); return ret;
}
staticint fill_trt(char __user *ubuf)
{ int i; int ret; int count; int trt_len; struct trt *trts = NULL; union trt_object *trt_user;
ret = acpi_parse_trt(acpi_thermal_rel_handle, &count, &trts, false); if (ret) goto free_trt;
trt_len = count * sizeof(union trt_object);
trt_user = kzalloc(trt_len, GFP_KERNEL); if (!trt_user) {
ret = -ENOMEM; goto free_trt;
} /* now fill in user trt data */ for (i = 0; i < count; i++) { /* userspace trt needs device name instead of acpi reference */
get_single_name(trts[i].source, trt_user[i].source_device);
get_single_name(trts[i].target, trt_user[i].target_device);
trt_user[i].sample_period = trts[i].sample_period;
trt_user[i].influence = trts[i].influence;
}
if (copy_to_user(ubuf, trt_user, trt_len))
ret = -EFAULT;
kfree(trt_user);
free_trt:
kfree(trts); return ret;
}
staticint fill_psvt(char __user *ubuf)
{ int i, ret, count, psvt_len; union psvt_object *psvt_user; struct psvt *psvts;
ret = acpi_parse_psvt(acpi_thermal_rel_handle, &count, &psvts); if (ret) return ret;
psvt_len = count * sizeof(*psvt_user);
psvt_user = kzalloc(psvt_len, GFP_KERNEL); if (!psvt_user) {
ret = -ENOMEM; goto free_psvt;
}
/* now fill in user psvt data */ for (i = 0; i < count; i++) { /* userspace psvt needs device name instead of acpi reference */
get_single_name(psvts[i].source, psvt_user[i].source_device);
get_single_name(psvts[i].target, psvt_user[i].target_device);
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.