hsmp.c (969f915473d8cb0e298234ee313370b6a2da69f3) hsmp.c (8e75dff56e003cdd38643024c4f5f8ba227100c8)
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * AMD HSMP Platform Driver
4 * Copyright (c) 2022, AMD.
5 * All Rights Reserved.
6 *
7 * This file provides a device implementation for HSMP interface
8 */

--- 25 unchanged lines hidden (view full) ---

34
35/* Timeout in millsec */
36#define HSMP_MSG_TIMEOUT 100
37#define HSMP_SHORT_SLEEP 1
38
39#define HSMP_WR true
40#define HSMP_RD false
41
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * AMD HSMP Platform Driver
4 * Copyright (c) 2022, AMD.
5 * All Rights Reserved.
6 *
7 * This file provides a device implementation for HSMP interface
8 */

--- 25 unchanged lines hidden (view full) ---

34
35/* Timeout in millsec */
36#define HSMP_MSG_TIMEOUT 100
37#define HSMP_SHORT_SLEEP 1
38
39#define HSMP_WR true
40#define HSMP_RD false
41
42struct hsmp_plat_device plat_dev;
42struct hsmp_plat_device hsmp_pdev;
43
44/*
45 * Send a message to the HSMP port via PCI-e config space registers
46 * or by writing to MMIO space.
47 *
48 * The caller is expected to zero out any unused arguments.
49 * If a response is expected, the number of response words should be greater than 0.
50 *

--- 120 unchanged lines hidden (view full) ---

171 int ret;
172
173 if (!msg)
174 return -EINVAL;
175 ret = validate_message(msg);
176 if (ret)
177 return ret;
178
43
44/*
45 * Send a message to the HSMP port via PCI-e config space registers
46 * or by writing to MMIO space.
47 *
48 * The caller is expected to zero out any unused arguments.
49 * If a response is expected, the number of response words should be greater than 0.
50 *

--- 120 unchanged lines hidden (view full) ---

171 int ret;
172
173 if (!msg)
174 return -EINVAL;
175 ret = validate_message(msg);
176 if (ret)
177 return ret;
178
179 if (!plat_dev.sock || msg->sock_ind >= plat_dev.num_sockets)
179 if (!hsmp_pdev.sock || msg->sock_ind >= hsmp_pdev.num_sockets)
180 return -ENODEV;
180 return -ENODEV;
181 sock = &plat_dev.sock[msg->sock_ind];
181 sock = &hsmp_pdev.sock[msg->sock_ind];
182
183 /*
184 * The time taken by smu operation to complete is between
185 * 10us to 1ms. Sometime it may take more time.
186 * In SMP system timeout of 100 millisecs should
187 * be enough for the previous thread to finish the operation
188 */
189 ret = down_timeout(&sock->hsmp_sem, msecs_to_jiffies(HSMP_MSG_TIMEOUT));

--- 24 unchanged lines hidden (view full) ---

214 msg.sock_ind = sock_ind;
215
216 ret = hsmp_send_message(&msg);
217 if (ret)
218 return ret;
219
220 /* Check the response value */
221 if (msg.args[0] != (value + 1)) {
182
183 /*
184 * The time taken by smu operation to complete is between
185 * 10us to 1ms. Sometime it may take more time.
186 * In SMP system timeout of 100 millisecs should
187 * be enough for the previous thread to finish the operation
188 */
189 ret = down_timeout(&sock->hsmp_sem, msecs_to_jiffies(HSMP_MSG_TIMEOUT));

--- 24 unchanged lines hidden (view full) ---

214 msg.sock_ind = sock_ind;
215
216 ret = hsmp_send_message(&msg);
217 if (ret)
218 return ret;
219
220 /* Check the response value */
221 if (msg.args[0] != (value + 1)) {
222 dev_err(plat_dev.sock[sock_ind].dev,
222 dev_err(hsmp_pdev.sock[sock_ind].dev,
223 "Socket %d test message failed, Expected 0x%08X, received 0x%08X\n",
224 sock_ind, (value + 1), msg.args[0]);
225 return -EBADE;
226 }
227
228 return ret;
229}
230

--- 84 unchanged lines hidden (view full) ---

315 return ret;
316 memcpy_fromio(buf, sock->metric_tbl_addr, bin_attr->size);
317
318 return bin_attr->size;
319}
320
321static int hsmp_get_tbl_dram_base(u16 sock_ind)
322{
223 "Socket %d test message failed, Expected 0x%08X, received 0x%08X\n",
224 sock_ind, (value + 1), msg.args[0]);
225 return -EBADE;
226 }
227
228 return ret;
229}
230

--- 84 unchanged lines hidden (view full) ---

315 return ret;
316 memcpy_fromio(buf, sock->metric_tbl_addr, bin_attr->size);
317
318 return bin_attr->size;
319}
320
321static int hsmp_get_tbl_dram_base(u16 sock_ind)
322{
323 struct hsmp_socket *sock = &plat_dev.sock[sock_ind];
323 struct hsmp_socket *sock = &hsmp_pdev.sock[sock_ind];
324 struct hsmp_message msg = { 0 };
325 phys_addr_t dram_addr;
326 int ret;
327
328 msg.sock_ind = sock_ind;
329 msg.response_sz = hsmp_msg_desc_table[HSMP_GET_METRIC_TABLE_DRAM_ADDR].response_sz;
330 msg.msg_id = HSMP_GET_METRIC_TABLE_DRAM_ADDR;
331

--- 17 unchanged lines hidden (view full) ---

349 return -ENOMEM;
350 }
351 return 0;
352}
353
354umode_t hsmp_is_sock_attr_visible(struct kobject *kobj,
355 struct bin_attribute *battr, int id)
356{
324 struct hsmp_message msg = { 0 };
325 phys_addr_t dram_addr;
326 int ret;
327
328 msg.sock_ind = sock_ind;
329 msg.response_sz = hsmp_msg_desc_table[HSMP_GET_METRIC_TABLE_DRAM_ADDR].response_sz;
330 msg.msg_id = HSMP_GET_METRIC_TABLE_DRAM_ADDR;
331

--- 17 unchanged lines hidden (view full) ---

349 return -ENOMEM;
350 }
351 return 0;
352}
353
354umode_t hsmp_is_sock_attr_visible(struct kobject *kobj,
355 struct bin_attribute *battr, int id)
356{
357 if (plat_dev.proto_ver == HSMP_PROTO_VER6)
357 if (hsmp_pdev.proto_ver == HSMP_PROTO_VER6)
358 return battr->attr.mode;
359 else
360 return 0;
361}
362
363static int hsmp_init_metric_tbl_bin_attr(struct bin_attribute **hattrs, u16 sock_ind)
364{
358 return battr->attr.mode;
359 else
360 return 0;
361}
362
363static int hsmp_init_metric_tbl_bin_attr(struct bin_attribute **hattrs, u16 sock_ind)
364{
365 struct bin_attribute *hattr = &plat_dev.sock[sock_ind].hsmp_attr;
365 struct bin_attribute *hattr = &hsmp_pdev.sock[sock_ind].hsmp_attr;
366
367 sysfs_bin_attr_init(hattr);
368 hattr->attr.name = HSMP_METRICS_TABLE_NAME;
369 hattr->attr.mode = 0444;
370 hattr->read = hsmp_metric_tbl_read;
371 hattr->size = sizeof(struct hsmp_metric_table);
366
367 sysfs_bin_attr_init(hattr);
368 hattr->attr.name = HSMP_METRICS_TABLE_NAME;
369 hattr->attr.mode = 0444;
370 hattr->read = hsmp_metric_tbl_read;
371 hattr->size = sizeof(struct hsmp_metric_table);
372 hattr->private = &plat_dev.sock[sock_ind];
372 hattr->private = &hsmp_pdev.sock[sock_ind];
373 hattrs[0] = hattr;
374
373 hattrs[0] = hattr;
374
375 if (plat_dev.proto_ver == HSMP_PROTO_VER6)
375 if (hsmp_pdev.proto_ver == HSMP_PROTO_VER6)
376 return hsmp_get_tbl_dram_base(sock_ind);
377 else
378 return 0;
379}
380
381/* One bin sysfs for metrics table */
382#define NUM_HSMP_ATTRS 1
383

--- 20 unchanged lines hidden (view full) ---

404 int ret;
405
406 msg.msg_id = HSMP_GET_PROTO_VER;
407 msg.sock_ind = sock_ind;
408 msg.response_sz = hsmp_msg_desc_table[HSMP_GET_PROTO_VER].response_sz;
409
410 ret = hsmp_send_message(&msg);
411 if (!ret)
376 return hsmp_get_tbl_dram_base(sock_ind);
377 else
378 return 0;
379}
380
381/* One bin sysfs for metrics table */
382#define NUM_HSMP_ATTRS 1
383

--- 20 unchanged lines hidden (view full) ---

404 int ret;
405
406 msg.msg_id = HSMP_GET_PROTO_VER;
407 msg.sock_ind = sock_ind;
408 msg.response_sz = hsmp_msg_desc_table[HSMP_GET_PROTO_VER].response_sz;
409
410 ret = hsmp_send_message(&msg);
411 if (!ret)
412 plat_dev.proto_ver = msg.args[0];
412 hsmp_pdev.proto_ver = msg.args[0];
413
414 return ret;
415}
416
417static const struct acpi_device_id amd_hsmp_acpi_ids[] = {
418 {ACPI_HSMP_DEVICE_HID, 0},
419 {}
420};

--- 15 unchanged lines hidden (view full) ---

436
437 /*
438 * On ACPI supported BIOS, there is an ACPI HSMP device added for
439 * each socket, so the per socket probing, but the memory allocated for
440 * sockets should be contiguous to access it as an array,
441 * Hence allocate memory for all the sockets at once instead of allocating
442 * on each probe.
443 */
413
414 return ret;
415}
416
417static const struct acpi_device_id amd_hsmp_acpi_ids[] = {
418 {ACPI_HSMP_DEVICE_HID, 0},
419 {}
420};

--- 15 unchanged lines hidden (view full) ---

436
437 /*
438 * On ACPI supported BIOS, there is an ACPI HSMP device added for
439 * each socket, so the per socket probing, but the memory allocated for
440 * sockets should be contiguous to access it as an array,
441 * Hence allocate memory for all the sockets at once instead of allocating
442 * on each probe.
443 */
444 if (!plat_dev.is_probed) {
445 plat_dev.sock = devm_kcalloc(&pdev->dev, plat_dev.num_sockets,
446 sizeof(*plat_dev.sock),
447 GFP_KERNEL);
448 if (!plat_dev.sock)
444 if (!hsmp_pdev.is_probed) {
445 hsmp_pdev.sock = devm_kcalloc(&pdev->dev, hsmp_pdev.num_sockets,
446 sizeof(*hsmp_pdev.sock),
447 GFP_KERNEL);
448 if (!hsmp_pdev.sock)
449 return -ENOMEM;
450 }
451 if (check_acpi_support(&pdev->dev)) {
452 ret = init_acpi(&pdev->dev);
453 if (ret) {
454 dev_err(&pdev->dev, "Failed to init HSMP mailbox\n");
455 return ret;
456 }

--- 6 unchanged lines hidden (view full) ---

463 dev_err(&pdev->dev, "Failed to init HSMP mailbox\n");
464 return ret;
465 }
466 ret = hsmp_create_non_acpi_sysfs_if(&pdev->dev);
467 if (ret)
468 dev_err(&pdev->dev, "Failed to create HSMP sysfs interface\n");
469 }
470
449 return -ENOMEM;
450 }
451 if (check_acpi_support(&pdev->dev)) {
452 ret = init_acpi(&pdev->dev);
453 if (ret) {
454 dev_err(&pdev->dev, "Failed to init HSMP mailbox\n");
455 return ret;
456 }

--- 6 unchanged lines hidden (view full) ---

463 dev_err(&pdev->dev, "Failed to init HSMP mailbox\n");
464 return ret;
465 }
466 ret = hsmp_create_non_acpi_sysfs_if(&pdev->dev);
467 if (ret)
468 dev_err(&pdev->dev, "Failed to create HSMP sysfs interface\n");
469 }
470
471 if (!plat_dev.is_probed) {
472 plat_dev.hsmp_device.name = HSMP_CDEV_NAME;
473 plat_dev.hsmp_device.minor = MISC_DYNAMIC_MINOR;
474 plat_dev.hsmp_device.fops = &hsmp_fops;
475 plat_dev.hsmp_device.parent = &pdev->dev;
476 plat_dev.hsmp_device.nodename = HSMP_DEVNODE_NAME;
477 plat_dev.hsmp_device.mode = 0644;
471 if (!hsmp_pdev.is_probed) {
472 hsmp_pdev.mdev.name = HSMP_CDEV_NAME;
473 hsmp_pdev.mdev.minor = MISC_DYNAMIC_MINOR;
474 hsmp_pdev.mdev.fops = &hsmp_fops;
475 hsmp_pdev.mdev.parent = &pdev->dev;
476 hsmp_pdev.mdev.nodename = HSMP_DEVNODE_NAME;
477 hsmp_pdev.mdev.mode = 0644;
478
478
479 ret = misc_register(&plat_dev.hsmp_device);
479 ret = misc_register(&hsmp_pdev.mdev);
480 if (ret)
481 return ret;
482
480 if (ret)
481 return ret;
482
483 plat_dev.is_probed = true;
483 hsmp_pdev.is_probed = true;
484 }
485
486 return 0;
487
488}
489
490static void hsmp_pltdrv_remove(struct platform_device *pdev)
491{
492 /*
493 * We register only one misc_device even on multi socket system.
494 * So, deregister should happen only once.
495 */
484 }
485
486 return 0;
487
488}
489
490static void hsmp_pltdrv_remove(struct platform_device *pdev)
491{
492 /*
493 * We register only one misc_device even on multi socket system.
494 * So, deregister should happen only once.
495 */
496 if (plat_dev.is_probed) {
497 misc_deregister(&plat_dev.hsmp_device);
498 plat_dev.is_probed = false;
496 if (hsmp_pdev.is_probed) {
497 misc_deregister(&hsmp_pdev.mdev);
498 hsmp_pdev.is_probed = false;
499 }
500}
501
502static struct platform_driver amd_hsmp_driver = {
503 .probe = hsmp_pltdrv_probe,
504 .remove = hsmp_pltdrv_remove,
505 .driver = {
506 .name = DRIVER_NAME,

--- 55 unchanged lines hidden (view full) ---

562static int __init hsmp_plt_init(void)
563{
564 int ret = -ENODEV;
565
566 /*
567 * amd_nb_num() returns number of SMN/DF interfaces present in the system
568 * if we have N SMN/DF interfaces that ideally means N sockets
569 */
499 }
500}
501
502static struct platform_driver amd_hsmp_driver = {
503 .probe = hsmp_pltdrv_probe,
504 .remove = hsmp_pltdrv_remove,
505 .driver = {
506 .name = DRIVER_NAME,

--- 55 unchanged lines hidden (view full) ---

562static int __init hsmp_plt_init(void)
563{
564 int ret = -ENODEV;
565
566 /*
567 * amd_nb_num() returns number of SMN/DF interfaces present in the system
568 * if we have N SMN/DF interfaces that ideally means N sockets
569 */
570 plat_dev.num_sockets = amd_nb_num();
571 if (plat_dev.num_sockets == 0 || plat_dev.num_sockets > MAX_AMD_SOCKETS)
570 hsmp_pdev.num_sockets = amd_nb_num();
571 if (hsmp_pdev.num_sockets == 0 || hsmp_pdev.num_sockets > MAX_AMD_SOCKETS)
572 return ret;
573
574 ret = platform_driver_register(&amd_hsmp_driver);
575 if (ret)
576 return ret;
577
572 return ret;
573
574 ret = platform_driver_register(&amd_hsmp_driver);
575 if (ret)
576 return ret;
577
578 if (!plat_dev.is_acpi_device) {
578 if (!hsmp_pdev.is_acpi_device) {
579 if (legacy_hsmp_support()) {
580 /* Not ACPI device, but supports HSMP, register a plat_dev */
581 ret = hsmp_plat_dev_register();
582 } else {
583 /* Not ACPI, Does not support HSMP */
584 pr_info("HSMP is not supported on Family:%x model:%x\n",
585 boot_cpu_data.x86, boot_cpu_data.x86_model);
586 ret = -ENODEV;

--- 20 unchanged lines hidden ---
579 if (legacy_hsmp_support()) {
580 /* Not ACPI device, but supports HSMP, register a plat_dev */
581 ret = hsmp_plat_dev_register();
582 } else {
583 /* Not ACPI, Does not support HSMP */
584 pr_info("HSMP is not supported on Family:%x model:%x\n",
585 boot_cpu_data.x86, boot_cpu_data.x86_model);
586 ret = -ENODEV;

--- 20 unchanged lines hidden ---