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 --- |