1 /* 2 * Copyright 2020 Advanced Micro Devices, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 */ 22 23 #define SWSMU_CODE_LAYER_L4 24 25 #include "amdgpu.h" 26 #include "amdgpu_smu.h" 27 #include "smu_cmn.h" 28 #include "soc15_common.h" 29 30 /* 31 * DO NOT use these for err/warn/info/debug messages. 32 * Use dev_err, dev_warn, dev_info and dev_dbg instead. 33 * They are more MGPU friendly. 34 */ 35 #undef pr_err 36 #undef pr_warn 37 #undef pr_info 38 #undef pr_debug 39 40 #define MP1_C2PMSG_90__CONTENT_MASK 0xFFFFFFFFL 41 42 #undef __SMU_DUMMY_MAP 43 #define __SMU_DUMMY_MAP(type) #type 44 static const char * const __smu_message_names[] = { 45 SMU_MESSAGE_TYPES 46 }; 47 48 #define smu_cmn_call_asic_func(intf, smu, args...) \ 49 ((smu)->ppt_funcs ? ((smu)->ppt_funcs->intf ? \ 50 (smu)->ppt_funcs->intf(smu, ##args) : \ 51 -ENOTSUPP) : \ 52 -EINVAL) 53 54 static const char *smu_get_message_name(struct smu_context *smu, 55 enum smu_message_type type) 56 { 57 if (type < 0 || type >= SMU_MSG_MAX_COUNT) 58 return "unknown smu message"; 59 60 return __smu_message_names[type]; 61 } 62 63 static void smu_cmn_read_arg(struct smu_context *smu, 64 uint32_t *arg) 65 { 66 struct amdgpu_device *adev = smu->adev; 67 68 *arg = RREG32(smu->param_reg); 69 } 70 71 /* Redefine the SMU error codes here. 72 * 73 * Note that these definitions are redundant and should be removed 74 * when the SMU has exported a unified header file containing these 75 * macros, which header file we can just include and use the SMU's 76 * macros. At the moment, these error codes are defined by the SMU 77 * per-ASIC unfortunately, yet we're a one driver for all ASICs. 78 */ 79 #define SMU_RESP_NONE 0 80 #define SMU_RESP_OK 1 81 #define SMU_RESP_CMD_FAIL 0xFF 82 #define SMU_RESP_CMD_UNKNOWN 0xFE 83 #define SMU_RESP_CMD_BAD_PREREQ 0xFD 84 #define SMU_RESP_BUSY_OTHER 0xFC 85 #define SMU_RESP_DEBUG_END 0xFB 86 87 /** 88 * __smu_cmn_poll_stat -- poll for a status from the SMU 89 * @smu: a pointer to SMU context 90 * 91 * Returns the status of the SMU, which could be, 92 * 0, the SMU is busy with your command; 93 * 1, execution status: success, execution result: success; 94 * 0xFF, execution status: success, execution result: failure; 95 * 0xFE, unknown command; 96 * 0xFD, valid command, but bad (command) prerequisites; 97 * 0xFC, the command was rejected as the SMU is busy; 98 * 0xFB, "SMC_Result_DebugDataDumpEnd". 99 * 100 * The values here are not defined by macros, because I'd rather we 101 * include a single header file which defines them, which is 102 * maintained by the SMU FW team, so that we're impervious to firmware 103 * changes. At the moment those values are defined in various header 104 * files, one for each ASIC, yet here we're a single ASIC-agnostic 105 * interface. Such a change can be followed-up by a subsequent patch. 106 */ 107 static u32 __smu_cmn_poll_stat(struct smu_context *smu) 108 { 109 struct amdgpu_device *adev = smu->adev; 110 int timeout = adev->usec_timeout * 20; 111 u32 reg; 112 113 for ( ; timeout > 0; timeout--) { 114 reg = RREG32(smu->resp_reg); 115 if ((reg & MP1_C2PMSG_90__CONTENT_MASK) != 0) 116 break; 117 118 udelay(1); 119 } 120 121 return reg; 122 } 123 124 static void __smu_cmn_reg_print_error(struct smu_context *smu, 125 u32 reg_c2pmsg_90, 126 int msg_index, 127 u32 param, 128 enum smu_message_type msg) 129 { 130 struct amdgpu_device *adev = smu->adev; 131 const char *message = smu_get_message_name(smu, msg); 132 u32 msg_idx, prm; 133 134 switch (reg_c2pmsg_90) { 135 case SMU_RESP_NONE: { 136 msg_idx = RREG32(smu->msg_reg); 137 prm = RREG32(smu->param_reg); 138 dev_err_ratelimited(adev->dev, 139 "SMU: I'm not done with your previous command: SMN_C2PMSG_66:0x%08X SMN_C2PMSG_82:0x%08X", 140 msg_idx, prm); 141 } 142 break; 143 case SMU_RESP_OK: 144 /* The SMU executed the command. It completed with a 145 * successful result. 146 */ 147 break; 148 case SMU_RESP_CMD_FAIL: 149 /* The SMU executed the command. It completed with an 150 * unsuccessful result. 151 */ 152 break; 153 case SMU_RESP_CMD_UNKNOWN: 154 dev_err_ratelimited(adev->dev, 155 "SMU: unknown command: index:%d param:0x%08X message:%s", 156 msg_index, param, message); 157 break; 158 case SMU_RESP_CMD_BAD_PREREQ: 159 dev_err_ratelimited(adev->dev, 160 "SMU: valid command, bad prerequisites: index:%d param:0x%08X message:%s", 161 msg_index, param, message); 162 break; 163 case SMU_RESP_BUSY_OTHER: 164 dev_err_ratelimited(adev->dev, 165 "SMU: I'm very busy for your command: index:%d param:0x%08X message:%s", 166 msg_index, param, message); 167 break; 168 case SMU_RESP_DEBUG_END: 169 dev_err_ratelimited(adev->dev, 170 "SMU: I'm debugging!"); 171 break; 172 default: 173 dev_err_ratelimited(adev->dev, 174 "SMU: response:0x%08X for index:%d param:0x%08X message:%s?", 175 reg_c2pmsg_90, msg_index, param, message); 176 break; 177 } 178 } 179 180 static int __smu_cmn_reg2errno(struct smu_context *smu, u32 reg_c2pmsg_90) 181 { 182 int res; 183 184 switch (reg_c2pmsg_90) { 185 case SMU_RESP_NONE: 186 /* The SMU is busy--still executing your command. 187 */ 188 res = -ETIME; 189 break; 190 case SMU_RESP_OK: 191 res = 0; 192 break; 193 case SMU_RESP_CMD_FAIL: 194 /* Command completed successfully, but the command 195 * status was failure. 196 */ 197 res = -EIO; 198 break; 199 case SMU_RESP_CMD_UNKNOWN: 200 /* Unknown command--ignored by the SMU. 201 */ 202 res = -EOPNOTSUPP; 203 break; 204 case SMU_RESP_CMD_BAD_PREREQ: 205 /* Valid command--bad prerequisites. 206 */ 207 res = -EINVAL; 208 break; 209 case SMU_RESP_BUSY_OTHER: 210 /* The SMU is busy with other commands. The client 211 * should retry in 10 us. 212 */ 213 res = -EBUSY; 214 break; 215 default: 216 /* Unknown or debug response from the SMU. 217 */ 218 res = -EREMOTEIO; 219 break; 220 } 221 222 return res; 223 } 224 225 static void __smu_cmn_send_msg(struct smu_context *smu, 226 u16 msg, 227 u32 param) 228 { 229 struct amdgpu_device *adev = smu->adev; 230 231 WREG32(smu->resp_reg, 0); 232 WREG32(smu->param_reg, param); 233 WREG32(smu->msg_reg, msg); 234 } 235 236 static int __smu_cmn_send_debug_msg(struct smu_context *smu, 237 u32 msg, 238 u32 param) 239 { 240 struct amdgpu_device *adev = smu->adev; 241 242 WREG32(smu->debug_param_reg, param); 243 WREG32(smu->debug_msg_reg, msg); 244 WREG32(smu->debug_resp_reg, 0); 245 246 return 0; 247 } 248 /** 249 * smu_cmn_send_msg_without_waiting -- send the message; don't wait for status 250 * @smu: pointer to an SMU context 251 * @msg_index: message index 252 * @param: message parameter to send to the SMU 253 * 254 * Send a message to the SMU with the parameter passed. Do not wait 255 * for status/result of the message, thus the "without_waiting". 256 * 257 * Return 0 on success, -errno on error if we weren't able to _send_ 258 * the message for some reason. See __smu_cmn_reg2errno() for details 259 * of the -errno. 260 */ 261 int smu_cmn_send_msg_without_waiting(struct smu_context *smu, 262 uint16_t msg_index, 263 uint32_t param) 264 { 265 struct amdgpu_device *adev = smu->adev; 266 u32 reg; 267 int res; 268 269 if (adev->no_hw_access) 270 return 0; 271 272 reg = __smu_cmn_poll_stat(smu); 273 res = __smu_cmn_reg2errno(smu, reg); 274 if (reg == SMU_RESP_NONE || 275 res == -EREMOTEIO) 276 goto Out; 277 __smu_cmn_send_msg(smu, msg_index, param); 278 res = 0; 279 Out: 280 if (unlikely(adev->pm.smu_debug_mask & SMU_DEBUG_HALT_ON_ERROR) && 281 res && (res != -ETIME)) { 282 amdgpu_device_halt(adev); 283 WARN_ON(1); 284 } 285 286 return res; 287 } 288 289 /** 290 * smu_cmn_wait_for_response -- wait for response from the SMU 291 * @smu: pointer to an SMU context 292 * 293 * Wait for status from the SMU. 294 * 295 * Return 0 on success, -errno on error, indicating the execution 296 * status and result of the message being waited for. See 297 * __smu_cmn_reg2errno() for details of the -errno. 298 */ 299 int smu_cmn_wait_for_response(struct smu_context *smu) 300 { 301 u32 reg; 302 int res; 303 304 reg = __smu_cmn_poll_stat(smu); 305 res = __smu_cmn_reg2errno(smu, reg); 306 307 if (unlikely(smu->adev->pm.smu_debug_mask & SMU_DEBUG_HALT_ON_ERROR) && 308 res && (res != -ETIME)) { 309 amdgpu_device_halt(smu->adev); 310 WARN_ON(1); 311 } 312 313 return res; 314 } 315 316 /** 317 * smu_cmn_send_smc_msg_with_param -- send a message with parameter 318 * @smu: pointer to an SMU context 319 * @msg: message to send 320 * @param: parameter to send to the SMU 321 * @read_arg: pointer to u32 to return a value from the SMU back 322 * to the caller 323 * 324 * Send the message @msg with parameter @param to the SMU, wait for 325 * completion of the command, and return back a value from the SMU in 326 * @read_arg pointer. 327 * 328 * Return 0 on success, -errno when a problem is encountered sending 329 * message or receiving reply. If there is a PCI bus recovery or 330 * the destination is a virtual GPU which does not allow this message 331 * type, the message is simply dropped and success is also returned. 332 * See __smu_cmn_reg2errno() for details of the -errno. 333 * 334 * If we weren't able to send the message to the SMU, we also print 335 * the error to the standard log. 336 * 337 * Command completion status is printed only if the -errno is 338 * -EREMOTEIO, indicating that the SMU returned back an 339 * undefined/unknown/unspecified result. All other cases are 340 * well-defined, not printed, but instead given back to the client to 341 * decide what further to do. 342 * 343 * The return value, @read_arg is read back regardless, to give back 344 * more information to the client, which on error would most likely be 345 * @param, but we can't assume that. This also eliminates more 346 * conditionals. 347 */ 348 int smu_cmn_send_smc_msg_with_param(struct smu_context *smu, 349 enum smu_message_type msg, 350 uint32_t param, 351 uint32_t *read_arg) 352 { 353 struct amdgpu_device *adev = smu->adev; 354 int res, index; 355 u32 reg; 356 357 if (adev->no_hw_access) 358 return 0; 359 360 index = smu_cmn_to_asic_specific_index(smu, 361 CMN2ASIC_MAPPING_MSG, 362 msg); 363 if (index < 0) 364 return index == -EACCES ? 0 : index; 365 366 mutex_lock(&smu->message_lock); 367 reg = __smu_cmn_poll_stat(smu); 368 res = __smu_cmn_reg2errno(smu, reg); 369 if (reg == SMU_RESP_NONE || 370 res == -EREMOTEIO) { 371 __smu_cmn_reg_print_error(smu, reg, index, param, msg); 372 goto Out; 373 } 374 __smu_cmn_send_msg(smu, (uint16_t) index, param); 375 reg = __smu_cmn_poll_stat(smu); 376 res = __smu_cmn_reg2errno(smu, reg); 377 if (res != 0) 378 __smu_cmn_reg_print_error(smu, reg, index, param, msg); 379 if (read_arg) 380 smu_cmn_read_arg(smu, read_arg); 381 Out: 382 if (unlikely(adev->pm.smu_debug_mask & SMU_DEBUG_HALT_ON_ERROR) && res) { 383 amdgpu_device_halt(adev); 384 WARN_ON(1); 385 } 386 387 mutex_unlock(&smu->message_lock); 388 return res; 389 } 390 391 int smu_cmn_send_smc_msg(struct smu_context *smu, 392 enum smu_message_type msg, 393 uint32_t *read_arg) 394 { 395 return smu_cmn_send_smc_msg_with_param(smu, 396 msg, 397 0, 398 read_arg); 399 } 400 401 int smu_cmn_send_debug_smc_msg(struct smu_context *smu, 402 uint32_t msg) 403 { 404 return __smu_cmn_send_debug_msg(smu, msg, 0); 405 } 406 407 int smu_cmn_to_asic_specific_index(struct smu_context *smu, 408 enum smu_cmn2asic_mapping_type type, 409 uint32_t index) 410 { 411 struct cmn2asic_msg_mapping msg_mapping; 412 struct cmn2asic_mapping mapping; 413 414 switch (type) { 415 case CMN2ASIC_MAPPING_MSG: 416 if (index >= SMU_MSG_MAX_COUNT || 417 !smu->message_map) 418 return -EINVAL; 419 420 msg_mapping = smu->message_map[index]; 421 if (!msg_mapping.valid_mapping) 422 return -EINVAL; 423 424 if (amdgpu_sriov_vf(smu->adev) && 425 !msg_mapping.valid_in_vf) 426 return -EACCES; 427 428 return msg_mapping.map_to; 429 430 case CMN2ASIC_MAPPING_CLK: 431 if (index >= SMU_CLK_COUNT || 432 !smu->clock_map) 433 return -EINVAL; 434 435 mapping = smu->clock_map[index]; 436 if (!mapping.valid_mapping) 437 return -EINVAL; 438 439 return mapping.map_to; 440 441 case CMN2ASIC_MAPPING_FEATURE: 442 if (index >= SMU_FEATURE_COUNT || 443 !smu->feature_map) 444 return -EINVAL; 445 446 mapping = smu->feature_map[index]; 447 if (!mapping.valid_mapping) 448 return -EINVAL; 449 450 return mapping.map_to; 451 452 case CMN2ASIC_MAPPING_TABLE: 453 if (index >= SMU_TABLE_COUNT || 454 !smu->table_map) 455 return -EINVAL; 456 457 mapping = smu->table_map[index]; 458 if (!mapping.valid_mapping) 459 return -EINVAL; 460 461 return mapping.map_to; 462 463 case CMN2ASIC_MAPPING_PWR: 464 if (index >= SMU_POWER_SOURCE_COUNT || 465 !smu->pwr_src_map) 466 return -EINVAL; 467 468 mapping = smu->pwr_src_map[index]; 469 if (!mapping.valid_mapping) 470 return -EINVAL; 471 472 return mapping.map_to; 473 474 case CMN2ASIC_MAPPING_WORKLOAD: 475 if (index > PP_SMC_POWER_PROFILE_WINDOW3D || 476 !smu->workload_map) 477 return -EINVAL; 478 479 mapping = smu->workload_map[index]; 480 if (!mapping.valid_mapping) 481 return -EINVAL; 482 483 return mapping.map_to; 484 485 default: 486 return -EINVAL; 487 } 488 } 489 490 int smu_cmn_feature_is_supported(struct smu_context *smu, 491 enum smu_feature_mask mask) 492 { 493 struct smu_feature *feature = &smu->smu_feature; 494 int feature_id; 495 496 feature_id = smu_cmn_to_asic_specific_index(smu, 497 CMN2ASIC_MAPPING_FEATURE, 498 mask); 499 if (feature_id < 0) 500 return 0; 501 502 WARN_ON(feature_id > feature->feature_num); 503 504 return test_bit(feature_id, feature->supported); 505 } 506 507 static int __smu_get_enabled_features(struct smu_context *smu, 508 uint64_t *enabled_features) 509 { 510 return smu_cmn_call_asic_func(get_enabled_mask, smu, enabled_features); 511 } 512 513 int smu_cmn_feature_is_enabled(struct smu_context *smu, 514 enum smu_feature_mask mask) 515 { 516 struct amdgpu_device *adev = smu->adev; 517 uint64_t enabled_features; 518 int feature_id; 519 520 if (__smu_get_enabled_features(smu, &enabled_features)) { 521 dev_err(adev->dev, "Failed to retrieve enabled ppfeatures!\n"); 522 return 0; 523 } 524 525 /* 526 * For Renoir and Cyan Skillfish, they are assumed to have all features 527 * enabled. Also considering they have no feature_map available, the 528 * check here can avoid unwanted feature_map check below. 529 */ 530 if (enabled_features == ULLONG_MAX) 531 return 1; 532 533 feature_id = smu_cmn_to_asic_specific_index(smu, 534 CMN2ASIC_MAPPING_FEATURE, 535 mask); 536 if (feature_id < 0) 537 return 0; 538 539 return test_bit(feature_id, (unsigned long *)&enabled_features); 540 } 541 542 bool smu_cmn_clk_dpm_is_enabled(struct smu_context *smu, 543 enum smu_clk_type clk_type) 544 { 545 enum smu_feature_mask feature_id = 0; 546 547 switch (clk_type) { 548 case SMU_MCLK: 549 case SMU_UCLK: 550 feature_id = SMU_FEATURE_DPM_UCLK_BIT; 551 break; 552 case SMU_GFXCLK: 553 case SMU_SCLK: 554 feature_id = SMU_FEATURE_DPM_GFXCLK_BIT; 555 break; 556 case SMU_SOCCLK: 557 feature_id = SMU_FEATURE_DPM_SOCCLK_BIT; 558 break; 559 case SMU_VCLK: 560 case SMU_VCLK1: 561 feature_id = SMU_FEATURE_DPM_VCLK_BIT; 562 break; 563 case SMU_DCLK: 564 case SMU_DCLK1: 565 feature_id = SMU_FEATURE_DPM_DCLK_BIT; 566 break; 567 case SMU_FCLK: 568 feature_id = SMU_FEATURE_DPM_FCLK_BIT; 569 break; 570 default: 571 return true; 572 } 573 574 if (!smu_cmn_feature_is_enabled(smu, feature_id)) 575 return false; 576 577 return true; 578 } 579 580 int smu_cmn_get_enabled_mask(struct smu_context *smu, 581 uint64_t *feature_mask) 582 { 583 uint32_t *feature_mask_high; 584 uint32_t *feature_mask_low; 585 int ret = 0, index = 0; 586 587 if (!feature_mask) 588 return -EINVAL; 589 590 feature_mask_low = &((uint32_t *)feature_mask)[0]; 591 feature_mask_high = &((uint32_t *)feature_mask)[1]; 592 593 index = smu_cmn_to_asic_specific_index(smu, 594 CMN2ASIC_MAPPING_MSG, 595 SMU_MSG_GetEnabledSmuFeatures); 596 if (index > 0) { 597 ret = smu_cmn_send_smc_msg_with_param(smu, 598 SMU_MSG_GetEnabledSmuFeatures, 599 0, 600 feature_mask_low); 601 if (ret) 602 return ret; 603 604 ret = smu_cmn_send_smc_msg_with_param(smu, 605 SMU_MSG_GetEnabledSmuFeatures, 606 1, 607 feature_mask_high); 608 } else { 609 ret = smu_cmn_send_smc_msg(smu, 610 SMU_MSG_GetEnabledSmuFeaturesHigh, 611 feature_mask_high); 612 if (ret) 613 return ret; 614 615 ret = smu_cmn_send_smc_msg(smu, 616 SMU_MSG_GetEnabledSmuFeaturesLow, 617 feature_mask_low); 618 } 619 620 return ret; 621 } 622 623 uint64_t smu_cmn_get_indep_throttler_status( 624 const unsigned long dep_status, 625 const uint8_t *throttler_map) 626 { 627 uint64_t indep_status = 0; 628 uint8_t dep_bit = 0; 629 630 for_each_set_bit(dep_bit, &dep_status, 32) 631 indep_status |= 1ULL << throttler_map[dep_bit]; 632 633 return indep_status; 634 } 635 636 int smu_cmn_feature_update_enable_state(struct smu_context *smu, 637 uint64_t feature_mask, 638 bool enabled) 639 { 640 int ret = 0; 641 642 if (enabled) { 643 ret = smu_cmn_send_smc_msg_with_param(smu, 644 SMU_MSG_EnableSmuFeaturesLow, 645 lower_32_bits(feature_mask), 646 NULL); 647 if (ret) 648 return ret; 649 ret = smu_cmn_send_smc_msg_with_param(smu, 650 SMU_MSG_EnableSmuFeaturesHigh, 651 upper_32_bits(feature_mask), 652 NULL); 653 } else { 654 ret = smu_cmn_send_smc_msg_with_param(smu, 655 SMU_MSG_DisableSmuFeaturesLow, 656 lower_32_bits(feature_mask), 657 NULL); 658 if (ret) 659 return ret; 660 ret = smu_cmn_send_smc_msg_with_param(smu, 661 SMU_MSG_DisableSmuFeaturesHigh, 662 upper_32_bits(feature_mask), 663 NULL); 664 } 665 666 return ret; 667 } 668 669 int smu_cmn_feature_set_enabled(struct smu_context *smu, 670 enum smu_feature_mask mask, 671 bool enable) 672 { 673 int feature_id; 674 675 feature_id = smu_cmn_to_asic_specific_index(smu, 676 CMN2ASIC_MAPPING_FEATURE, 677 mask); 678 if (feature_id < 0) 679 return -EINVAL; 680 681 return smu_cmn_feature_update_enable_state(smu, 682 1ULL << feature_id, 683 enable); 684 } 685 686 #undef __SMU_DUMMY_MAP 687 #define __SMU_DUMMY_MAP(fea) #fea 688 static const char* __smu_feature_names[] = { 689 SMU_FEATURE_MASKS 690 }; 691 692 static const char *smu_get_feature_name(struct smu_context *smu, 693 enum smu_feature_mask feature) 694 { 695 if (feature < 0 || feature >= SMU_FEATURE_COUNT) 696 return "unknown smu feature"; 697 return __smu_feature_names[feature]; 698 } 699 700 size_t smu_cmn_get_pp_feature_mask(struct smu_context *smu, 701 char *buf) 702 { 703 int8_t sort_feature[max(SMU_FEATURE_COUNT, SMU_FEATURE_MAX)]; 704 uint64_t feature_mask; 705 int i, feature_index; 706 uint32_t count = 0; 707 size_t size = 0; 708 709 if (__smu_get_enabled_features(smu, &feature_mask)) 710 return 0; 711 712 size = sysfs_emit_at(buf, size, "features high: 0x%08x low: 0x%08x\n", 713 upper_32_bits(feature_mask), lower_32_bits(feature_mask)); 714 715 memset(sort_feature, -1, sizeof(sort_feature)); 716 717 for (i = 0; i < SMU_FEATURE_COUNT; i++) { 718 feature_index = smu_cmn_to_asic_specific_index(smu, 719 CMN2ASIC_MAPPING_FEATURE, 720 i); 721 if (feature_index < 0) 722 continue; 723 724 sort_feature[feature_index] = i; 725 } 726 727 size += sysfs_emit_at(buf, size, "%-2s. %-20s %-3s : %-s\n", 728 "No", "Feature", "Bit", "State"); 729 730 for (feature_index = 0; feature_index < SMU_FEATURE_MAX; feature_index++) { 731 if (sort_feature[feature_index] < 0) 732 continue; 733 734 size += sysfs_emit_at(buf, size, "%02d. %-20s (%2d) : %s\n", 735 count++, 736 smu_get_feature_name(smu, sort_feature[feature_index]), 737 feature_index, 738 !!test_bit(feature_index, (unsigned long *)&feature_mask) ? 739 "enabled" : "disabled"); 740 } 741 742 return size; 743 } 744 745 int smu_cmn_set_pp_feature_mask(struct smu_context *smu, 746 uint64_t new_mask) 747 { 748 int ret = 0; 749 uint64_t feature_mask; 750 uint64_t feature_2_enabled = 0; 751 uint64_t feature_2_disabled = 0; 752 753 ret = __smu_get_enabled_features(smu, &feature_mask); 754 if (ret) 755 return ret; 756 757 feature_2_enabled = ~feature_mask & new_mask; 758 feature_2_disabled = feature_mask & ~new_mask; 759 760 if (feature_2_enabled) { 761 ret = smu_cmn_feature_update_enable_state(smu, 762 feature_2_enabled, 763 true); 764 if (ret) 765 return ret; 766 } 767 if (feature_2_disabled) { 768 ret = smu_cmn_feature_update_enable_state(smu, 769 feature_2_disabled, 770 false); 771 if (ret) 772 return ret; 773 } 774 775 return ret; 776 } 777 778 /** 779 * smu_cmn_disable_all_features_with_exception - disable all dpm features 780 * except this specified by 781 * @mask 782 * 783 * @smu: smu_context pointer 784 * @mask: the dpm feature which should not be disabled 785 * SMU_FEATURE_COUNT: no exception, all dpm features 786 * to disable 787 * 788 * Returns: 789 * 0 on success or a negative error code on failure. 790 */ 791 int smu_cmn_disable_all_features_with_exception(struct smu_context *smu, 792 enum smu_feature_mask mask) 793 { 794 uint64_t features_to_disable = U64_MAX; 795 int skipped_feature_id; 796 797 if (mask != SMU_FEATURE_COUNT) { 798 skipped_feature_id = smu_cmn_to_asic_specific_index(smu, 799 CMN2ASIC_MAPPING_FEATURE, 800 mask); 801 if (skipped_feature_id < 0) 802 return -EINVAL; 803 804 features_to_disable &= ~(1ULL << skipped_feature_id); 805 } 806 807 return smu_cmn_feature_update_enable_state(smu, 808 features_to_disable, 809 0); 810 } 811 812 int smu_cmn_get_smc_version(struct smu_context *smu, 813 uint32_t *if_version, 814 uint32_t *smu_version) 815 { 816 int ret = 0; 817 818 if (!if_version && !smu_version) 819 return -EINVAL; 820 821 if (smu->smc_fw_if_version && smu->smc_fw_version) 822 { 823 if (if_version) 824 *if_version = smu->smc_fw_if_version; 825 826 if (smu_version) 827 *smu_version = smu->smc_fw_version; 828 829 return 0; 830 } 831 832 if (if_version) { 833 ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetDriverIfVersion, if_version); 834 if (ret) 835 return ret; 836 837 smu->smc_fw_if_version = *if_version; 838 } 839 840 if (smu_version) { 841 ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetSmuVersion, smu_version); 842 if (ret) 843 return ret; 844 845 smu->smc_fw_version = *smu_version; 846 } 847 848 return ret; 849 } 850 851 int smu_cmn_update_table(struct smu_context *smu, 852 enum smu_table_id table_index, 853 int argument, 854 void *table_data, 855 bool drv2smu) 856 { 857 struct smu_table_context *smu_table = &smu->smu_table; 858 struct amdgpu_device *adev = smu->adev; 859 struct smu_table *table = &smu_table->driver_table; 860 int table_id = smu_cmn_to_asic_specific_index(smu, 861 CMN2ASIC_MAPPING_TABLE, 862 table_index); 863 uint32_t table_size; 864 int ret = 0; 865 if (!table_data || table_id >= SMU_TABLE_COUNT || table_id < 0) 866 return -EINVAL; 867 868 table_size = smu_table->tables[table_index].size; 869 870 if (drv2smu) { 871 memcpy(table->cpu_addr, table_data, table_size); 872 /* 873 * Flush hdp cache: to guard the content seen by 874 * GPU is consitent with CPU. 875 */ 876 amdgpu_asic_flush_hdp(adev, NULL); 877 } 878 879 ret = smu_cmn_send_smc_msg_with_param(smu, drv2smu ? 880 SMU_MSG_TransferTableDram2Smu : 881 SMU_MSG_TransferTableSmu2Dram, 882 table_id | ((argument & 0xFFFF) << 16), 883 NULL); 884 if (ret) 885 return ret; 886 887 if (!drv2smu) { 888 amdgpu_asic_invalidate_hdp(adev, NULL); 889 memcpy(table_data, table->cpu_addr, table_size); 890 } 891 892 return 0; 893 } 894 895 int smu_cmn_write_watermarks_table(struct smu_context *smu) 896 { 897 void *watermarks_table = smu->smu_table.watermarks_table; 898 899 if (!watermarks_table) 900 return -EINVAL; 901 902 return smu_cmn_update_table(smu, 903 SMU_TABLE_WATERMARKS, 904 0, 905 watermarks_table, 906 true); 907 } 908 909 int smu_cmn_write_pptable(struct smu_context *smu) 910 { 911 void *pptable = smu->smu_table.driver_pptable; 912 913 return smu_cmn_update_table(smu, 914 SMU_TABLE_PPTABLE, 915 0, 916 pptable, 917 true); 918 } 919 920 int smu_cmn_get_metrics_table(struct smu_context *smu, 921 void *metrics_table, 922 bool bypass_cache) 923 { 924 struct smu_table_context *smu_table= &smu->smu_table; 925 uint32_t table_size = 926 smu_table->tables[SMU_TABLE_SMU_METRICS].size; 927 int ret = 0; 928 929 if (bypass_cache || 930 !smu_table->metrics_time || 931 time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(1))) { 932 ret = smu_cmn_update_table(smu, 933 SMU_TABLE_SMU_METRICS, 934 0, 935 smu_table->metrics_table, 936 false); 937 if (ret) { 938 dev_info(smu->adev->dev, "Failed to export SMU metrics table!\n"); 939 return ret; 940 } 941 smu_table->metrics_time = jiffies; 942 } 943 944 if (metrics_table) 945 memcpy(metrics_table, smu_table->metrics_table, table_size); 946 947 return 0; 948 } 949 950 int smu_cmn_get_combo_pptable(struct smu_context *smu) 951 { 952 void *pptable = smu->smu_table.combo_pptable; 953 954 return smu_cmn_update_table(smu, 955 SMU_TABLE_COMBO_PPTABLE, 956 0, 957 pptable, 958 false); 959 } 960 961 void smu_cmn_init_soft_gpu_metrics(void *table, uint8_t frev, uint8_t crev) 962 { 963 struct metrics_table_header *header = (struct metrics_table_header *)table; 964 uint16_t structure_size; 965 966 #define METRICS_VERSION(a, b) ((a << 16) | b ) 967 968 switch (METRICS_VERSION(frev, crev)) { 969 case METRICS_VERSION(1, 0): 970 structure_size = sizeof(struct gpu_metrics_v1_0); 971 break; 972 case METRICS_VERSION(1, 1): 973 structure_size = sizeof(struct gpu_metrics_v1_1); 974 break; 975 case METRICS_VERSION(1, 2): 976 structure_size = sizeof(struct gpu_metrics_v1_2); 977 break; 978 case METRICS_VERSION(1, 3): 979 structure_size = sizeof(struct gpu_metrics_v1_3); 980 break; 981 case METRICS_VERSION(2, 0): 982 structure_size = sizeof(struct gpu_metrics_v2_0); 983 break; 984 case METRICS_VERSION(2, 1): 985 structure_size = sizeof(struct gpu_metrics_v2_1); 986 break; 987 case METRICS_VERSION(2, 2): 988 structure_size = sizeof(struct gpu_metrics_v2_2); 989 break; 990 case METRICS_VERSION(2, 3): 991 structure_size = sizeof(struct gpu_metrics_v2_3); 992 break; 993 default: 994 return; 995 } 996 997 #undef METRICS_VERSION 998 999 memset(header, 0xFF, structure_size); 1000 1001 header->format_revision = frev; 1002 header->content_revision = crev; 1003 header->structure_size = structure_size; 1004 1005 } 1006 1007 int smu_cmn_set_mp1_state(struct smu_context *smu, 1008 enum pp_mp1_state mp1_state) 1009 { 1010 enum smu_message_type msg; 1011 int ret; 1012 1013 switch (mp1_state) { 1014 case PP_MP1_STATE_SHUTDOWN: 1015 msg = SMU_MSG_PrepareMp1ForShutdown; 1016 break; 1017 case PP_MP1_STATE_UNLOAD: 1018 msg = SMU_MSG_PrepareMp1ForUnload; 1019 break; 1020 case PP_MP1_STATE_RESET: 1021 msg = SMU_MSG_PrepareMp1ForReset; 1022 break; 1023 case PP_MP1_STATE_NONE: 1024 default: 1025 return 0; 1026 } 1027 1028 ret = smu_cmn_send_smc_msg(smu, msg, NULL); 1029 if (ret) 1030 dev_err(smu->adev->dev, "[PrepareMp1] Failed!\n"); 1031 1032 return ret; 1033 } 1034 1035 bool smu_cmn_is_audio_func_enabled(struct amdgpu_device *adev) 1036 { 1037 struct pci_dev *p = NULL; 1038 bool snd_driver_loaded; 1039 1040 /* 1041 * If the ASIC comes with no audio function, we always assume 1042 * it is "enabled". 1043 */ 1044 p = pci_get_domain_bus_and_slot(pci_domain_nr(adev->pdev->bus), 1045 adev->pdev->bus->number, 1); 1046 if (!p) 1047 return true; 1048 1049 snd_driver_loaded = pci_is_enabled(p) ? true : false; 1050 1051 pci_dev_put(p); 1052 1053 return snd_driver_loaded; 1054 } 1055