/* These are the strings specified in ACPI table */ #define MSG_IDOFF_STR "MsgIdOffset" #define MSG_ARGOFF_STR "MsgArgOffset" #define MSG_RESPOFF_STR "MsgRspOffset"
/* This is the UUID used for HSMP */ staticconst guid_t acpi_hsmp_uuid = GUID_INIT(0xb74d619d, 0x5707, 0x48bd,
0xa6, 0x9f, 0x4e, 0xa2,
0x87, 0x1f, 0xc2, 0xf6);
/* * UID (ID00, ID01..IDXX) is used for differentiating sockets, * read it and strip the "ID" part of it and convert the remaining * bytes to integer.
*/
uid = acpi_device_uid(ACPI_COMPANION(dev));
switch (res->type) { case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: if (!acpi_dev_resource_memory(res, &r)) return AE_ERROR; if (!r.start || r.end < r.start || !(r.flags & IORESOURCE_MEM_WRITEABLE)) return AE_ERROR;
sock->mbinfo.base_addr = r.start;
sock->mbinfo.size = resource_size(&r); break; case ACPI_RESOURCE_TYPE_END_TAG: break; default: return AE_ERROR;
}
return AE_OK;
}
staticint hsmp_read_acpi_dsd(struct hsmp_socket *sock)
{ struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *guid, *mailbox_package; union acpi_object *dsd;
acpi_status status; int ret = 0; int j;
status = acpi_evaluate_object_typed(ACPI_HANDLE(sock->dev), "_DSD", NULL,
&buf, ACPI_TYPE_PACKAGE); if (ACPI_FAILURE(status)) {
dev_err(sock->dev, "Failed to read mailbox reg offsets from DSD table, err: %s\n",
acpi_format_exception(status)); return -ENODEV;
}
dsd = buf.pointer;
/* HSMP _DSD property should contain 2 objects. * 1. guid which is an acpi object of type ACPI_TYPE_BUFFER * 2. mailbox which is an acpi object of type ACPI_TYPE_PACKAGE * This mailbox object contains 3 more acpi objects of type * ACPI_TYPE_PACKAGE for holding msgid, msgresp, msgarg offsets * these packages inturn contain 2 acpi objects of type * ACPI_TYPE_STRING and ACPI_TYPE_INTEGER
*/ if (!dsd || dsd->type != ACPI_TYPE_PACKAGE || dsd->package.count != 2) {
ret = -EINVAL; goto free_buf;
}
status = acpi_walk_resources(ACPI_HANDLE(sock->dev), METHOD_NAME__CRS,
hsmp_resource, sock); if (ACPI_FAILURE(status)) {
dev_err(sock->dev, "Failed to look up MP1 base address from CRS method, err: %s\n",
acpi_format_exception(status)); return -EINVAL;
} if (!sock->mbinfo.base_addr || !sock->mbinfo.size) return -EINVAL;
/* The mapped region should be un-cached */
sock->virt_base_addr = devm_ioremap_uc(sock->dev, sock->mbinfo.base_addr,
sock->mbinfo.size); if (!sock->virt_base_addr) {
dev_err(sock->dev, "Failed to ioremap MP1 base address\n"); return -ENOMEM;
}
return 0;
}
/* Parse the ACPI table to read the data */ staticint hsmp_parse_acpi_table(struct device *dev, u16 sock_ind)
{ struct hsmp_socket *sock = &hsmp_pdev->sock[sock_ind]; int ret;
ret = hsmp_msg_get_nargs(sock->sock_ind, hattr->msg_id, &data, 1); if (ret) return ret;
src_ind = FIELD_GET(FREQ_SRC_IND_MASK, data); for (index = 0; index < ARRAY_SIZE(freqlimit_srcnames); index++) { if (!src_ind) break; if (src_ind & 1)
len += sysfs_emit_at(buf, len, "%s\n", freqlimit_srcnames[index]);
src_ind >>= 1;
} return len;
}
staticint init_acpi(struct device *dev)
{
u16 sock_ind; int ret;
ret = hsmp_get_uid(dev, &sock_ind); if (ret) return ret; if (sock_ind >= hsmp_pdev->num_sockets) return -EINVAL;
ret = hsmp_parse_acpi_table(dev, sock_ind); if (ret) {
dev_err(dev, "Failed to parse ACPI table\n"); return ret;
}
/* Test the hsmp interface */
ret = hsmp_test(sock_ind, 0xDEADBEEF); if (ret) {
dev_err(dev, "HSMP test message failed on Fam:%x model:%x\n",
boot_cpu_data.x86, boot_cpu_data.x86_model);
dev_err(dev, "Is HSMP disabled in BIOS ?\n"); return ret;
}
ret = hsmp_cache_proto_ver(sock_ind); if (ret) {
dev_err(dev, "Failed to read HSMP protocol version\n"); return ret;
}
if (hsmp_pdev->proto_ver == HSMP_PROTO_VER6) {
ret = hsmp_get_tbl_dram_base(sock_ind); if (ret)
dev_err(dev, "Failed to init metric table\n");
}
ret = hsmp_create_sensor(dev, sock_ind); if (ret)
dev_err(dev, "Failed to register HSMP sensors with hwmon\n");
ret = init_acpi(&pdev->dev); if (ret) {
dev_err(&pdev->dev, "Failed to initialize HSMP interface.\n"); return ret;
}
if (!hsmp_pdev->is_probed) {
ret = hsmp_misc_register(&pdev->dev); if (ret) {
dev_err(&pdev->dev, "Failed to register misc device\n"); return ret;
}
hsmp_pdev->is_probed = true;
dev_dbg(&pdev->dev, "AMD HSMP ACPI is probed successfully\n");
}
return 0;
}
staticvoid hsmp_acpi_remove(struct platform_device *pdev)
{ /* * We register only one misc_device even on multi-socket system. * So, deregister should happen only once.
*/ if (hsmp_pdev->is_probed) {
hsmp_misc_deregister();
hsmp_pdev->is_probed = false;
}
}
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.