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 const int link_speed[] = {25, 50, 80, 160, 320, 640}; 43 44 #undef __SMU_DUMMY_MAP 45 #define __SMU_DUMMY_MAP(type) #type 46 static const char * const __smu_message_names[] = { 47 SMU_MESSAGE_TYPES 48 }; 49 50 #define smu_cmn_call_asic_func(intf, smu, args...) \ 51 ((smu)->ppt_funcs ? ((smu)->ppt_funcs->intf ? \ 52 (smu)->ppt_funcs->intf(smu, ##args) : \ 53 -ENOTSUPP) : \ 54 -EINVAL) 55 56 #define SMU_MSG_V1_DEFAULT_RATELIMIT_INTERVAL (5 * HZ) 57 #define SMU_MSG_V1_DEFAULT_RATELIMIT_BURST 10 58 59 static const char *smu_get_message_name(struct smu_context *smu, 60 enum smu_message_type type) 61 { 62 if (type >= SMU_MSG_MAX_COUNT) 63 return "unknown smu message"; 64 65 return __smu_message_names[type]; 66 } 67 68 /* Redefine the SMU error codes here. 69 * 70 * Note that these definitions are redundant and should be removed 71 * when the SMU has exported a unified header file containing these 72 * macros, which header file we can just include and use the SMU's 73 * macros. At the moment, these error codes are defined by the SMU 74 * per-ASIC unfortunately, yet we're a one driver for all ASICs. 75 */ 76 #define SMU_RESP_NONE 0 77 #define SMU_RESP_OK 1 78 #define SMU_RESP_CMD_FAIL 0xFF 79 #define SMU_RESP_CMD_UNKNOWN 0xFE 80 #define SMU_RESP_CMD_BAD_PREREQ 0xFD 81 #define SMU_RESP_BUSY_OTHER 0xFC 82 #define SMU_RESP_DEBUG_END 0xFB 83 84 #define SMU_RESP_UNEXP (~0U) 85 86 static int smu_msg_v1_send_debug_msg(struct smu_msg_ctl *ctl, u32 msg, u32 param) 87 { 88 struct amdgpu_device *adev = ctl->smu->adev; 89 struct smu_msg_config *cfg = &ctl->config; 90 91 if (!(ctl->flags & SMU_MSG_CTL_DEBUG_MAILBOX)) 92 return -EOPNOTSUPP; 93 94 mutex_lock(&ctl->lock); 95 96 WREG32(cfg->debug_param_reg, param); 97 WREG32(cfg->debug_msg_reg, msg); 98 WREG32(cfg->debug_resp_reg, 0); 99 100 mutex_unlock(&ctl->lock); 101 102 return 0; 103 } 104 105 static int __smu_cmn_send_debug_msg(struct smu_msg_ctl *ctl, 106 u32 msg, 107 u32 param) 108 { 109 if (!ctl->ops || !ctl->ops->send_debug_msg) 110 return -EOPNOTSUPP; 111 112 return ctl->ops->send_debug_msg(ctl, msg, param); 113 } 114 115 /** 116 * smu_cmn_wait_for_response -- wait for response from the SMU 117 * @smu: pointer to an SMU context 118 * 119 * Wait for status from the SMU. 120 * 121 * Return 0 on success, -errno on error, indicating the execution 122 * status and result of the message being waited for. See 123 * smu_msg_v1_decode_response() for details of the -errno. 124 */ 125 int smu_cmn_wait_for_response(struct smu_context *smu) 126 { 127 return smu_msg_wait_response(&smu->msg_ctl, 0); 128 } 129 130 /** 131 * smu_cmn_send_smc_msg_with_params_ext - send an SMU message with 0..N args 132 * @smu: pointer to an SMU context 133 * @msg: message to send 134 * @params: optional input argument array 135 * @num_params: number of input arguments in @params 136 * @read_args: optional output argument array 137 * @num_read_args: number of output arguments to read back 138 * @flags: message flags (SMU_MSG_FLAG_*) 139 * @timeout: per-message timeout in us (0 = use default) 140 * 141 * This helper keeps the raw protocol semantics of struct smu_msg_args while 142 * hiding the per-call boilerplate. It is intended for true multi-parameter 143 * messages. Legacy wrappers such as smu_cmn_send_smc_msg() retain their 144 * existing single-zero-parameter behavior for compatibility. 145 * 146 * Return: 0 on success, -errno on failure. 147 */ 148 int smu_cmn_send_smc_msg_with_params_ext(struct smu_context *smu, 149 enum smu_message_type msg, 150 const uint32_t *params, 151 size_t num_params, 152 uint32_t *read_args, 153 size_t num_read_args, 154 uint32_t flags, 155 uint32_t timeout) 156 { 157 struct smu_msg_ctl *ctl = &smu->msg_ctl; 158 struct smu_msg_args args = { 159 .msg = msg, 160 .num_args = num_params, 161 .num_out_args = num_read_args, 162 .flags = flags, 163 .timeout = timeout, 164 }; 165 int ret; 166 167 if ((num_params && !params) || (num_read_args && !read_args)) 168 return -EINVAL; 169 170 if (num_params > SMU_MSG_MAX_ARGS || num_read_args > SMU_MSG_MAX_ARGS) 171 return -EINVAL; 172 173 if (num_params) 174 memcpy(args.args, params, num_params * sizeof(*params)); 175 176 ret = ctl->ops->send_msg(ctl, &args); 177 178 if (num_read_args) 179 memcpy(read_args, args.out_args, 180 num_read_args * sizeof(*read_args)); 181 182 return ret; 183 } 184 185 /** 186 * smu_cmn_send_smc_msg_with_param -- send a message with parameter 187 * @smu: pointer to an SMU context 188 * @msg: message to send 189 * @param: parameter to send to the SMU 190 * @read_arg: pointer to u32 to return a value from the SMU back 191 * to the caller 192 * 193 * Send the message @msg with parameter @param to the SMU, wait for 194 * completion of the command, and return back a value from the SMU in 195 * @read_arg pointer. 196 * 197 * Return 0 on success, -errno when a problem is encountered sending 198 * message or receiving reply. If there is a PCI bus recovery or 199 * the destination is a virtual GPU which does not allow this message 200 * type, the message is simply dropped and success is also returned. 201 * See smu_msg_v1_decode_response() for details of the -errno. 202 * 203 * If we weren't able to send the message to the SMU, we also print 204 * the error to the standard log. 205 * 206 * Command completion status is printed only if the -errno is 207 * -EREMOTEIO, indicating that the SMU returned back an 208 * undefined/unknown/unspecified result. All other cases are 209 * well-defined, not printed, but instead given back to the client to 210 * decide what further to do. 211 * 212 * The return value, @read_arg is read back regardless, to give back 213 * more information to the client, which on error would most likely be 214 * @param, but we can't assume that. This also eliminates more 215 * conditionals. 216 */ 217 int smu_cmn_send_smc_msg_with_param(struct smu_context *smu, 218 enum smu_message_type msg, 219 uint32_t param, 220 uint32_t *read_arg) 221 { 222 return smu_cmn_send_smc_msg_with_params(smu, msg, 223 ¶m, 1, 224 read_arg, read_arg ? 1 : 0); 225 } 226 227 int smu_cmn_send_smc_msg(struct smu_context *smu, 228 enum smu_message_type msg, 229 uint32_t *read_arg) 230 { 231 return smu_cmn_send_smc_msg_with_param(smu, 232 msg, 233 0, 234 read_arg); 235 } 236 237 int smu_cmn_send_debug_smc_msg(struct smu_context *smu, 238 uint32_t msg) 239 { 240 return __smu_cmn_send_debug_msg(&smu->msg_ctl, msg, 0); 241 } 242 243 int smu_cmn_send_debug_smc_msg_with_param(struct smu_context *smu, 244 uint32_t msg, uint32_t param) 245 { 246 return __smu_cmn_send_debug_msg(&smu->msg_ctl, msg, param); 247 } 248 249 static int smu_msg_v1_decode_response(u32 resp) 250 { 251 int res; 252 253 switch (resp) { 254 case SMU_RESP_NONE: 255 /* The SMU is busy--still executing your command. 256 */ 257 res = -ETIME; 258 break; 259 case SMU_RESP_OK: 260 res = 0; 261 break; 262 case SMU_RESP_CMD_FAIL: 263 /* Command completed successfully, but the command 264 * status was failure. 265 */ 266 res = -EIO; 267 break; 268 case SMU_RESP_CMD_UNKNOWN: 269 /* Unknown command--ignored by the SMU. 270 */ 271 res = -EOPNOTSUPP; 272 break; 273 case SMU_RESP_CMD_BAD_PREREQ: 274 /* Valid command--bad prerequisites. 275 */ 276 res = -EINVAL; 277 break; 278 case SMU_RESP_BUSY_OTHER: 279 /* The SMU is busy with other commands. The client 280 * should retry in 10 us. 281 */ 282 res = -EBUSY; 283 break; 284 default: 285 /* Unknown or debug response from the SMU. 286 */ 287 res = -EREMOTEIO; 288 break; 289 } 290 291 return res; 292 } 293 294 static u32 __smu_msg_v1_poll_stat(struct smu_msg_ctl *ctl, u32 timeout_us) 295 { 296 struct amdgpu_device *adev = ctl->smu->adev; 297 struct smu_msg_config *cfg = &ctl->config; 298 u32 timeout = timeout_us ? timeout_us : ctl->default_timeout; 299 u32 reg; 300 301 for (; timeout > 0; timeout--) { 302 reg = RREG32(cfg->resp_reg); 303 if ((reg & MP1_C2PMSG_90__CONTENT_MASK) != 0) 304 break; 305 udelay(1); 306 } 307 308 return reg; 309 } 310 311 static void __smu_msg_v1_send(struct smu_msg_ctl *ctl, u16 index, 312 struct smu_msg_args *args) 313 { 314 struct amdgpu_device *adev = ctl->smu->adev; 315 struct smu_msg_config *cfg = &ctl->config; 316 u32 arg; 317 int i; 318 319 WREG32(cfg->resp_reg, 0); 320 for (i = 0; i < cfg->num_arg_regs; i++) { 321 /* NOTE: Clear unused argument registers to avoid stale values. */ 322 arg = i < args->num_args ? args->args[i] : 0; 323 WREG32(cfg->arg_regs[i], arg); 324 } 325 WREG32(cfg->msg_reg, index); 326 } 327 328 static void __smu_msg_v1_read_out_args(struct smu_msg_ctl *ctl, 329 struct smu_msg_args *args) 330 { 331 struct amdgpu_device *adev = ctl->smu->adev; 332 int i; 333 334 for (i = 0; i < args->num_out_args; i++) 335 args->out_args[i] = RREG32(ctl->config.arg_regs[i]); 336 } 337 338 static void __smu_msg_v1_print_err_limited(struct smu_msg_ctl *ctl, 339 struct smu_msg_args *args, 340 char *err_msg) 341 { 342 static DEFINE_RATELIMIT_STATE(_rs, 343 SMU_MSG_V1_DEFAULT_RATELIMIT_INTERVAL, 344 SMU_MSG_V1_DEFAULT_RATELIMIT_BURST); 345 struct smu_context *smu = ctl->smu; 346 struct amdgpu_device *adev = smu->adev; 347 348 if (__ratelimit(&_rs)) { 349 u32 in[SMU_MSG_MAX_ARGS]; 350 int i; 351 352 dev_err(adev->dev, "%s msg_reg: %x resp_reg: %x", err_msg, 353 RREG32(ctl->config.msg_reg), 354 RREG32(ctl->config.resp_reg)); 355 if (args->num_args > 0) { 356 for (i = 0; i < args->num_args; i++) 357 in[i] = RREG32(ctl->config.arg_regs[i]); 358 print_hex_dump(KERN_ERR, "in params:", DUMP_PREFIX_NONE, 359 16, 4, in, args->num_args * sizeof(u32), 360 false); 361 } 362 } 363 } 364 365 static void __smu_msg_v1_print_error(struct smu_msg_ctl *ctl, 366 u32 resp, 367 struct smu_msg_args *args) 368 { 369 struct smu_context *smu = ctl->smu; 370 struct amdgpu_device *adev = smu->adev; 371 int index = ctl->message_map[args->msg].map_to; 372 373 switch (resp) { 374 case SMU_RESP_NONE: 375 __smu_msg_v1_print_err_limited(ctl, args, "SMU: No response"); 376 break; 377 case SMU_RESP_OK: 378 break; 379 case SMU_RESP_CMD_FAIL: 380 break; 381 case SMU_RESP_CMD_UNKNOWN: 382 __smu_msg_v1_print_err_limited(ctl, args, 383 "SMU: unknown command"); 384 break; 385 case SMU_RESP_CMD_BAD_PREREQ: 386 __smu_msg_v1_print_err_limited( 387 ctl, args, "SMU: valid command, bad prerequisites"); 388 break; 389 case SMU_RESP_BUSY_OTHER: 390 if (args->msg != SMU_MSG_GetBadPageCount) 391 __smu_msg_v1_print_err_limited(ctl, args, 392 "SMU: I'm very busy"); 393 break; 394 case SMU_RESP_DEBUG_END: 395 __smu_msg_v1_print_err_limited(ctl, args, "SMU: Debug Err"); 396 break; 397 case SMU_RESP_UNEXP: 398 if (amdgpu_device_bus_status_check(adev)) { 399 dev_err(adev->dev, 400 "SMU: bus error for message: %s(%d) response:0x%08X ", 401 smu_get_message_name(smu, args->msg), index, 402 resp); 403 if (args->num_args > 0) 404 print_hex_dump(KERN_ERR, 405 "in params:", DUMP_PREFIX_NONE, 406 16, 4, args->args, 407 args->num_args * sizeof(u32), 408 false); 409 } 410 break; 411 default: 412 __smu_msg_v1_print_err_limited(ctl, args, 413 "SMU: unknown response"); 414 break; 415 } 416 } 417 418 static int __smu_msg_v1_ras_filter(struct smu_msg_ctl *ctl, 419 enum smu_message_type msg, u32 msg_flags, 420 bool *skip_pre_poll) 421 { 422 struct smu_context *smu = ctl->smu; 423 struct amdgpu_device *adev = smu->adev; 424 bool fed_status; 425 u32 reg; 426 427 if (!(smu->smc_fw_caps & SMU_FW_CAP_RAS_PRI)) 428 return 0; 429 430 fed_status = amdgpu_ras_get_fed_status(adev); 431 432 /* Block non-RAS-priority messages during RAS error */ 433 if (fed_status && !(msg_flags & SMU_MSG_RAS_PRI)) { 434 dev_dbg(adev->dev, "RAS error detected, skip sending %s", 435 smu_get_message_name(smu, msg)); 436 return -EACCES; 437 } 438 439 /* Skip pre-poll for priority messages or during RAS error */ 440 if ((msg_flags & SMU_MSG_NO_PRECHECK) || fed_status) { 441 reg = RREG32(ctl->config.resp_reg); 442 dev_dbg(adev->dev, 443 "Sending priority message %s response status: %x", 444 smu_get_message_name(smu, msg), reg); 445 if (reg == 0) 446 *skip_pre_poll = true; 447 } 448 449 return 0; 450 } 451 452 /** 453 * smu_msg_v1_send_msg - Complete V1 protocol with all filtering 454 * @ctl: Message control block 455 * @args: Message arguments 456 * 457 * Return: 0 on success, negative errno on failure 458 */ 459 static int smu_msg_v1_send_msg(struct smu_msg_ctl *ctl, 460 struct smu_msg_args *args) 461 { 462 struct smu_context *smu = ctl->smu; 463 struct amdgpu_device *adev = smu->adev; 464 const struct cmn2asic_msg_mapping *mapping; 465 u32 reg, msg_flags; 466 int ret, index; 467 bool skip_pre_poll = false; 468 bool lock_held = args->flags & SMU_MSG_FLAG_LOCK_HELD; 469 470 /* Early exit if no HW access */ 471 if (adev->no_hw_access) 472 return 0; 473 474 /* Message index translation */ 475 if (args->msg >= SMU_MSG_MAX_COUNT || !ctl->message_map) 476 return -EINVAL; 477 478 if (args->num_args > ctl->config.num_arg_regs || 479 args->num_out_args > ctl->config.num_arg_regs) 480 return -EINVAL; 481 482 mapping = &ctl->message_map[args->msg]; 483 if (!mapping->valid_mapping) 484 return -EINVAL; 485 486 msg_flags = mapping->flags; 487 index = mapping->map_to; 488 489 /* VF filter - skip messages not valid for VF */ 490 if (amdgpu_sriov_vf(adev) && !(msg_flags & SMU_MSG_VF_FLAG)) 491 return 0; 492 493 if (!lock_held) 494 mutex_lock(&ctl->lock); 495 496 /* RAS priority filter */ 497 ret = __smu_msg_v1_ras_filter(ctl, args->msg, msg_flags, 498 &skip_pre_poll); 499 if (ret) 500 goto out; 501 502 /* FW state checks */ 503 if (smu->smc_fw_state == SMU_FW_HANG) { 504 dev_err(adev->dev, 505 "SMU is in hanged state, failed to send smu message!\n"); 506 ret = -EREMOTEIO; 507 goto out; 508 } else if (smu->smc_fw_state == SMU_FW_INIT) { 509 skip_pre_poll = true; 510 smu->smc_fw_state = SMU_FW_RUNTIME; 511 } 512 513 /* Pre-poll: ensure previous message completed */ 514 if (!skip_pre_poll) { 515 reg = __smu_msg_v1_poll_stat(ctl, args->timeout); 516 ret = smu_msg_v1_decode_response(reg); 517 if (reg == SMU_RESP_NONE || ret == -EREMOTEIO) { 518 __smu_msg_v1_print_error(ctl, reg, args); 519 goto out; 520 } 521 } 522 523 /* Send message */ 524 __smu_msg_v1_send(ctl, (u16)index, args); 525 526 /* Post-poll (skip if ASYNC) */ 527 if (args->flags & SMU_MSG_FLAG_ASYNC) { 528 ret = 0; 529 goto out; 530 } 531 532 reg = __smu_msg_v1_poll_stat(ctl, args->timeout); 533 ret = smu_msg_v1_decode_response(reg); 534 535 /* FW state update on fatal error */ 536 if (ret == -EREMOTEIO) { 537 smu->smc_fw_state = SMU_FW_HANG; 538 __smu_msg_v1_print_error(ctl, reg, args); 539 } else if (ret != 0) { 540 __smu_msg_v1_print_error(ctl, reg, args); 541 } 542 543 /* Read output args */ 544 if ((ret == 0 || (args->flags & SMU_MSG_FLAG_FORCE_READ_ARG)) && 545 args->num_out_args > 0) { 546 __smu_msg_v1_read_out_args(ctl, args); 547 dev_dbg(adev->dev, "smu send message: %s(%d) resp : 0x%08x", 548 smu_get_message_name(smu, args->msg), index, reg); 549 if (args->num_args > 0) 550 print_hex_dump_debug("in params:", DUMP_PREFIX_NONE, 16, 551 4, args->args, 552 args->num_args * sizeof(u32), 553 false); 554 print_hex_dump_debug("out params:", DUMP_PREFIX_NONE, 16, 4, 555 args->out_args, 556 args->num_out_args * sizeof(u32), false); 557 } else { 558 dev_dbg(adev->dev, "smu send message: %s(%d), resp: 0x%08x\n", 559 smu_get_message_name(smu, args->msg), index, reg); 560 if (args->num_args > 0) 561 print_hex_dump_debug("in params:", DUMP_PREFIX_NONE, 16, 562 4, args->args, 563 args->num_args * sizeof(u32), 564 false); 565 } 566 567 out: 568 /* Debug halt on error */ 569 if (unlikely(adev->pm.smu_debug_mask & SMU_DEBUG_HALT_ON_ERROR) && 570 ret) { 571 amdgpu_device_halt(adev); 572 WARN_ON(1); 573 } 574 575 if (!lock_held) 576 mutex_unlock(&ctl->lock); 577 return ret; 578 } 579 580 static int smu_msg_v1_wait_response(struct smu_msg_ctl *ctl, u32 timeout_us) 581 { 582 struct smu_context *smu = ctl->smu; 583 struct amdgpu_device *adev = smu->adev; 584 u32 reg; 585 int ret; 586 587 reg = __smu_msg_v1_poll_stat(ctl, timeout_us); 588 ret = smu_msg_v1_decode_response(reg); 589 590 if (ret == -EREMOTEIO) 591 smu->smc_fw_state = SMU_FW_HANG; 592 593 if (unlikely(adev->pm.smu_debug_mask & SMU_DEBUG_HALT_ON_ERROR) && 594 ret && (ret != -ETIME)) { 595 amdgpu_device_halt(adev); 596 WARN_ON(1); 597 } 598 599 return ret; 600 } 601 602 const struct smu_msg_ops smu_msg_v1_ops = { 603 .send_msg = smu_msg_v1_send_msg, 604 .wait_response = smu_msg_v1_wait_response, 605 .decode_response = smu_msg_v1_decode_response, 606 .send_debug_msg = smu_msg_v1_send_debug_msg, 607 }; 608 609 int smu_msg_wait_response(struct smu_msg_ctl *ctl, u32 timeout_us) 610 { 611 return ctl->ops->wait_response(ctl, timeout_us); 612 } 613 614 /** 615 * smu_msg_send_async_locked - Send message asynchronously, caller holds lock 616 * @ctl: Message control block 617 * @msg: Message type 618 * @param: Message parameter 619 * 620 * Send an SMU message without waiting for response. Caller must hold ctl->lock 621 * and call smu_msg_wait_response() later to get the result. 622 * 623 * Return: 0 on success, negative errno on failure 624 */ 625 int smu_msg_send_async_locked(struct smu_msg_ctl *ctl, 626 enum smu_message_type msg, u32 param) 627 { 628 struct smu_msg_args args = { 629 .msg = msg, 630 .args[0] = param, 631 .num_args = 1, 632 .num_out_args = 0, 633 .flags = SMU_MSG_FLAG_ASYNC | SMU_MSG_FLAG_LOCK_HELD, 634 .timeout = 0, 635 }; 636 637 return ctl->ops->send_msg(ctl, &args); 638 } 639 640 int smu_cmn_to_asic_specific_index(struct smu_context *smu, 641 enum smu_cmn2asic_mapping_type type, 642 uint32_t index) 643 { 644 struct cmn2asic_msg_mapping msg_mapping; 645 struct cmn2asic_mapping mapping; 646 647 switch (type) { 648 case CMN2ASIC_MAPPING_MSG: 649 if (index >= SMU_MSG_MAX_COUNT || 650 !smu->msg_ctl.message_map) 651 return -EINVAL; 652 653 msg_mapping = smu->msg_ctl.message_map[index]; 654 if (!msg_mapping.valid_mapping) 655 return -EINVAL; 656 657 if (amdgpu_sriov_vf(smu->adev) && 658 !(msg_mapping.flags & SMU_MSG_VF_FLAG)) 659 return -EACCES; 660 661 return msg_mapping.map_to; 662 663 case CMN2ASIC_MAPPING_CLK: 664 if (index >= SMU_CLK_COUNT || 665 !smu->clock_map) 666 return -EINVAL; 667 668 mapping = smu->clock_map[index]; 669 if (!mapping.valid_mapping) 670 return -EINVAL; 671 672 return mapping.map_to; 673 674 case CMN2ASIC_MAPPING_FEATURE: 675 if (index >= SMU_FEATURE_COUNT || 676 !smu->feature_map) 677 return -EINVAL; 678 679 mapping = smu->feature_map[index]; 680 if (!mapping.valid_mapping) 681 return -EINVAL; 682 683 return mapping.map_to; 684 685 case CMN2ASIC_MAPPING_TABLE: 686 if (index >= SMU_TABLE_COUNT || 687 !smu->table_map) 688 return -EINVAL; 689 690 mapping = smu->table_map[index]; 691 if (!mapping.valid_mapping) 692 return -EINVAL; 693 694 return mapping.map_to; 695 696 case CMN2ASIC_MAPPING_PWR: 697 if (index >= SMU_POWER_SOURCE_COUNT || 698 !smu->pwr_src_map) 699 return -EINVAL; 700 701 mapping = smu->pwr_src_map[index]; 702 if (!mapping.valid_mapping) 703 return -EINVAL; 704 705 return mapping.map_to; 706 707 case CMN2ASIC_MAPPING_WORKLOAD: 708 if (index >= PP_SMC_POWER_PROFILE_COUNT || 709 !smu->workload_map) 710 return -EINVAL; 711 712 mapping = smu->workload_map[index]; 713 if (!mapping.valid_mapping) 714 return -ENOTSUPP; 715 716 return mapping.map_to; 717 718 default: 719 return -EINVAL; 720 } 721 } 722 723 int smu_cmn_feature_is_supported(struct smu_context *smu, 724 enum smu_feature_mask mask) 725 { 726 int feature_id; 727 728 feature_id = smu_cmn_to_asic_specific_index(smu, 729 CMN2ASIC_MAPPING_FEATURE, 730 mask); 731 if (feature_id < 0) 732 return 0; 733 734 return smu_feature_list_is_set(smu, SMU_FEATURE_LIST_SUPPORTED, 735 feature_id); 736 } 737 738 static int __smu_get_enabled_features(struct smu_context *smu, 739 struct smu_feature_bits *enabled_features) 740 { 741 return smu_cmn_call_asic_func(get_enabled_mask, smu, enabled_features); 742 } 743 744 int smu_cmn_feature_is_enabled(struct smu_context *smu, 745 enum smu_feature_mask mask) 746 { 747 struct amdgpu_device *adev = smu->adev; 748 struct smu_feature_bits enabled_features; 749 int feature_id; 750 751 if (__smu_get_enabled_features(smu, &enabled_features)) { 752 dev_err(adev->dev, "Failed to retrieve enabled ppfeatures!\n"); 753 return 0; 754 } 755 756 /* 757 * For Renoir and Cyan Skillfish, they are assumed to have all features 758 * enabled. Also considering they have no feature_map available, the 759 * check here can avoid unwanted feature_map check below. 760 */ 761 if (smu_feature_bits_full(&enabled_features, 762 smu->smu_feature.feature_num)) 763 return 1; 764 765 feature_id = smu_cmn_to_asic_specific_index(smu, 766 CMN2ASIC_MAPPING_FEATURE, 767 mask); 768 if (feature_id < 0) 769 return 0; 770 771 return smu_feature_bits_is_set(&enabled_features, feature_id); 772 } 773 774 bool smu_cmn_clk_dpm_is_enabled(struct smu_context *smu, 775 enum smu_clk_type clk_type) 776 { 777 enum smu_feature_mask feature_id = 0; 778 779 switch (clk_type) { 780 case SMU_MCLK: 781 case SMU_UCLK: 782 feature_id = SMU_FEATURE_DPM_UCLK_BIT; 783 break; 784 case SMU_GFXCLK: 785 case SMU_SCLK: 786 feature_id = SMU_FEATURE_DPM_GFXCLK_BIT; 787 break; 788 case SMU_SOCCLK: 789 feature_id = SMU_FEATURE_DPM_SOCCLK_BIT; 790 break; 791 case SMU_VCLK: 792 case SMU_VCLK1: 793 feature_id = SMU_FEATURE_DPM_VCLK_BIT; 794 break; 795 case SMU_DCLK: 796 case SMU_DCLK1: 797 feature_id = SMU_FEATURE_DPM_DCLK_BIT; 798 break; 799 case SMU_FCLK: 800 feature_id = SMU_FEATURE_DPM_FCLK_BIT; 801 break; 802 default: 803 return true; 804 } 805 806 if (!smu_cmn_feature_is_enabled(smu, feature_id)) 807 return false; 808 809 return true; 810 } 811 812 int smu_cmn_get_enabled_mask(struct smu_context *smu, 813 struct smu_feature_bits *feature_mask) 814 { 815 uint32_t features[2]; 816 int ret = 0, index = 0; 817 818 if (!feature_mask) 819 return -EINVAL; 820 821 index = smu_cmn_to_asic_specific_index(smu, 822 CMN2ASIC_MAPPING_MSG, 823 SMU_MSG_GetEnabledSmuFeatures); 824 if (index > 0) { 825 ret = smu_cmn_send_smc_msg_with_param( 826 smu, SMU_MSG_GetEnabledSmuFeatures, 0, &features[0]); 827 if (ret) 828 return ret; 829 830 ret = smu_cmn_send_smc_msg_with_param( 831 smu, SMU_MSG_GetEnabledSmuFeatures, 1, &features[1]); 832 } else { 833 ret = smu_cmn_send_smc_msg( 834 smu, SMU_MSG_GetEnabledSmuFeaturesHigh, &features[1]); 835 if (ret) 836 return ret; 837 838 ret = smu_cmn_send_smc_msg( 839 smu, SMU_MSG_GetEnabledSmuFeaturesLow, &features[0]); 840 } 841 842 if (!ret) 843 smu_feature_bits_from_arr32(feature_mask, features, 844 SMU_FEATURE_NUM_DEFAULT); 845 846 return ret; 847 } 848 849 uint64_t smu_cmn_get_indep_throttler_status( 850 const unsigned long dep_status, 851 const uint8_t *throttler_map) 852 { 853 uint64_t indep_status = 0; 854 uint8_t dep_bit = 0; 855 856 for_each_set_bit(dep_bit, &dep_status, 32) 857 indep_status |= 1ULL << throttler_map[dep_bit]; 858 859 return indep_status; 860 } 861 862 int smu_cmn_feature_update_enable_state(struct smu_context *smu, 863 uint64_t feature_mask, 864 bool enabled) 865 { 866 int ret = 0; 867 868 if (enabled) { 869 ret = smu_cmn_send_smc_msg_with_param(smu, 870 SMU_MSG_EnableSmuFeaturesLow, 871 lower_32_bits(feature_mask), 872 NULL); 873 if (ret) 874 return ret; 875 ret = smu_cmn_send_smc_msg_with_param(smu, 876 SMU_MSG_EnableSmuFeaturesHigh, 877 upper_32_bits(feature_mask), 878 NULL); 879 } else { 880 ret = smu_cmn_send_smc_msg_with_param(smu, 881 SMU_MSG_DisableSmuFeaturesLow, 882 lower_32_bits(feature_mask), 883 NULL); 884 if (ret) 885 return ret; 886 ret = smu_cmn_send_smc_msg_with_param(smu, 887 SMU_MSG_DisableSmuFeaturesHigh, 888 upper_32_bits(feature_mask), 889 NULL); 890 } 891 892 return ret; 893 } 894 895 int smu_cmn_feature_set_enabled(struct smu_context *smu, 896 enum smu_feature_mask mask, 897 bool enable) 898 { 899 int feature_id; 900 901 feature_id = smu_cmn_to_asic_specific_index(smu, 902 CMN2ASIC_MAPPING_FEATURE, 903 mask); 904 if (feature_id < 0) 905 return -EINVAL; 906 907 return smu_cmn_feature_update_enable_state(smu, 908 1ULL << feature_id, 909 enable); 910 } 911 912 #undef __SMU_DUMMY_MAP 913 #define __SMU_DUMMY_MAP(fea) #fea 914 static const char *__smu_feature_names[] = { 915 SMU_FEATURE_MASKS 916 }; 917 918 static const char *smu_get_feature_name(struct smu_context *smu, 919 enum smu_feature_mask feature) 920 { 921 if (feature >= SMU_FEATURE_COUNT) 922 return "unknown smu feature"; 923 return __smu_feature_names[feature]; 924 } 925 926 size_t smu_cmn_get_pp_feature_mask(struct smu_context *smu, 927 char *buf) 928 { 929 int16_t sort_feature[MAX(SMU_FEATURE_COUNT, SMU_FEATURE_MAX)]; 930 struct smu_feature_bits feature_mask; 931 uint32_t features[2]; 932 int i, feature_index; 933 uint32_t count = 0; 934 size_t size = 0; 935 936 if (__smu_get_enabled_features(smu, &feature_mask)) 937 return 0; 938 939 /* TBD: Need to handle for > 64 bits */ 940 smu_feature_bits_to_arr32(&feature_mask, features, 64); 941 size = sysfs_emit_at(buf, size, "features high: 0x%08x low: 0x%08x\n", 942 features[1], features[0]); 943 944 memset(sort_feature, -1, sizeof(sort_feature)); 945 946 for (i = 0; i < SMU_FEATURE_COUNT; i++) { 947 feature_index = smu_cmn_to_asic_specific_index(smu, 948 CMN2ASIC_MAPPING_FEATURE, 949 i); 950 if (feature_index < 0) 951 continue; 952 953 sort_feature[feature_index] = i; 954 } 955 956 size += sysfs_emit_at(buf, size, "%-2s. %-20s %-3s : %-s\n", 957 "No", "Feature", "Bit", "State"); 958 959 for (feature_index = 0; feature_index < smu->smu_feature.feature_num; 960 feature_index++) { 961 if (sort_feature[feature_index] < 0) 962 continue; 963 964 size += sysfs_emit_at( 965 buf, size, "%02d. %-20s (%2d) : %s\n", count++, 966 smu_get_feature_name(smu, sort_feature[feature_index]), 967 feature_index, 968 smu_feature_bits_is_set(&feature_mask, feature_index) ? 969 "enabled" : 970 "disabled"); 971 } 972 973 return size; 974 } 975 976 int smu_cmn_set_pp_feature_mask(struct smu_context *smu, 977 uint64_t new_mask) 978 { 979 int ret = 0; 980 struct smu_feature_bits feature_mask; 981 uint64_t feature_mask_u64; 982 uint64_t feature_2_enabled = 0; 983 uint64_t feature_2_disabled = 0; 984 985 ret = __smu_get_enabled_features(smu, &feature_mask); 986 if (ret) 987 return ret; 988 989 feature_mask_u64 = *(uint64_t *)feature_mask.bits; 990 feature_2_enabled = ~feature_mask_u64 & new_mask; 991 feature_2_disabled = feature_mask_u64 & ~new_mask; 992 993 if (feature_2_enabled) { 994 ret = smu_cmn_feature_update_enable_state(smu, 995 feature_2_enabled, 996 true); 997 if (ret) 998 return ret; 999 } 1000 if (feature_2_disabled) { 1001 ret = smu_cmn_feature_update_enable_state(smu, 1002 feature_2_disabled, 1003 false); 1004 if (ret) 1005 return ret; 1006 } 1007 1008 return ret; 1009 } 1010 1011 /** 1012 * smu_cmn_disable_all_features_with_exception - disable all dpm features 1013 * except this specified by 1014 * @mask 1015 * 1016 * @smu: smu_context pointer 1017 * @mask: the dpm feature which should not be disabled 1018 * SMU_FEATURE_COUNT: no exception, all dpm features 1019 * to disable 1020 * 1021 * Returns: 1022 * 0 on success or a negative error code on failure. 1023 */ 1024 int smu_cmn_disable_all_features_with_exception(struct smu_context *smu, 1025 enum smu_feature_mask mask) 1026 { 1027 uint64_t features_to_disable = U64_MAX; 1028 int skipped_feature_id; 1029 1030 if (mask != SMU_FEATURE_COUNT) { 1031 skipped_feature_id = smu_cmn_to_asic_specific_index(smu, 1032 CMN2ASIC_MAPPING_FEATURE, 1033 mask); 1034 if (skipped_feature_id < 0) 1035 return -EINVAL; 1036 1037 features_to_disable &= ~(1ULL << skipped_feature_id); 1038 } 1039 1040 return smu_cmn_feature_update_enable_state(smu, 1041 features_to_disable, 1042 0); 1043 } 1044 1045 int smu_cmn_get_smc_version(struct smu_context *smu, 1046 uint32_t *if_version, 1047 uint32_t *smu_version) 1048 { 1049 int ret = 0; 1050 1051 if (!if_version && !smu_version) 1052 return -EINVAL; 1053 1054 if (smu->smc_fw_if_version && smu->smc_fw_version) 1055 { 1056 if (if_version) 1057 *if_version = smu->smc_fw_if_version; 1058 1059 if (smu_version) 1060 *smu_version = smu->smc_fw_version; 1061 1062 return 0; 1063 } 1064 1065 if (if_version) { 1066 ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetDriverIfVersion, if_version); 1067 if (ret) 1068 return ret; 1069 1070 smu->smc_fw_if_version = *if_version; 1071 } 1072 1073 if (smu_version) { 1074 ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetSmuVersion, smu_version); 1075 if (ret) 1076 return ret; 1077 1078 smu->smc_fw_version = *smu_version; 1079 } 1080 1081 return ret; 1082 } 1083 1084 int smu_cmn_check_fw_version(struct smu_context *smu) 1085 { 1086 struct amdgpu_device *adev = smu->adev; 1087 uint32_t if_version = 0xff, smu_version = 0xff; 1088 uint8_t smu_program, smu_major, smu_minor, smu_debug; 1089 int ret; 1090 1091 ret = smu_cmn_get_smc_version(smu, &if_version, &smu_version); 1092 if (ret) 1093 return ret; 1094 1095 smu_program = (smu_version >> 24) & 0xff; 1096 smu_major = (smu_version >> 16) & 0xff; 1097 smu_minor = (smu_version >> 8) & 0xff; 1098 smu_debug = (smu_version >> 0) & 0xff; 1099 adev->pm.fw_version = smu_version; 1100 1101 dev_info_once(adev->dev, "smu driver if version = 0x%08x, smu fw if version = 0x%08x, " 1102 "smu fw program = %d, smu fw version = 0x%08x (%d.%d.%d)\n", 1103 smu->smc_driver_if_version, if_version, 1104 smu_program, smu_version, smu_major, smu_minor, smu_debug); 1105 1106 return 0; 1107 } 1108 1109 int smu_cmn_update_table_read_arg(struct smu_context *smu, 1110 enum smu_table_id table_index, 1111 int argument, 1112 void *table_data, 1113 uint32_t *read_arg, 1114 bool drv2smu) 1115 { 1116 struct amdgpu_device *adev = smu->adev; 1117 struct smu_table_context *smu_table = &smu->smu_table; 1118 struct smu_table *table = &smu_table->driver_table; 1119 int table_id = smu_cmn_to_asic_specific_index(smu, 1120 CMN2ASIC_MAPPING_TABLE, 1121 table_index); 1122 uint32_t table_size; 1123 int ret = 0; 1124 uint32_t param; 1125 1126 if (!table_data || table_index >= SMU_TABLE_COUNT || table_id < 0) 1127 return -EINVAL; 1128 1129 table_size = smu_table->tables[table_index].size; 1130 1131 if (drv2smu) { 1132 memcpy(table->cpu_addr, table_data, table_size); 1133 /* 1134 * Flush hdp cache: to guard the content seen by 1135 * GPU is consitent with CPU. 1136 */ 1137 amdgpu_hdp_flush(adev, NULL); 1138 } 1139 1140 param = ((argument & 0xFFFF) << 16) | (table_id & 0xffff); 1141 1142 ret = smu_cmn_send_smc_msg_with_params_ext( 1143 smu, 1144 drv2smu ? SMU_MSG_TransferTableDram2Smu : 1145 SMU_MSG_TransferTableSmu2Dram, 1146 ¶m, 1, read_arg, read_arg ? 1 : 0, 1147 read_arg ? SMU_MSG_FLAG_FORCE_READ_ARG : 0, 0); 1148 1149 if (ret) 1150 return ret; 1151 1152 if (!drv2smu) { 1153 amdgpu_hdp_invalidate(adev, NULL); 1154 memcpy(table_data, table->cpu_addr, table_size); 1155 } 1156 1157 return 0; 1158 } 1159 1160 int smu_cmn_vram_cpy(struct smu_context *smu, void *dst, const void *src, 1161 size_t len) 1162 { 1163 memcpy(dst, src, len); 1164 1165 /* Don't trust the copy operation if RAS fatal error happened. */ 1166 if (amdgpu_ras_get_fed_status(smu->adev)) 1167 return -EHWPOISON; 1168 1169 return 0; 1170 } 1171 1172 int smu_cmn_write_watermarks_table(struct smu_context *smu) 1173 { 1174 void *watermarks_table = smu->smu_table.watermarks_table; 1175 1176 if (!watermarks_table) 1177 return -EINVAL; 1178 1179 return smu_cmn_update_table(smu, 1180 SMU_TABLE_WATERMARKS, 1181 0, 1182 watermarks_table, 1183 true); 1184 } 1185 1186 int smu_cmn_write_pptable(struct smu_context *smu) 1187 { 1188 void *pptable = smu->smu_table.driver_pptable; 1189 1190 return smu_cmn_update_table(smu, 1191 SMU_TABLE_PPTABLE, 1192 0, 1193 pptable, 1194 true); 1195 } 1196 1197 int smu_cmn_get_metrics_table(struct smu_context *smu, 1198 void *metrics_table, 1199 bool bypass_cache) 1200 { 1201 struct smu_table_context *smu_table = &smu->smu_table; 1202 uint32_t table_size = 1203 smu_table->tables[SMU_TABLE_SMU_METRICS].size; 1204 int ret = 0; 1205 1206 if (bypass_cache || 1207 !smu_table->metrics_time || 1208 time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(1))) { 1209 ret = smu_cmn_update_table(smu, 1210 SMU_TABLE_SMU_METRICS, 1211 0, 1212 smu_table->metrics_table, 1213 false); 1214 if (ret) { 1215 dev_info(smu->adev->dev, "Failed to export SMU metrics table!\n"); 1216 return ret; 1217 } 1218 smu_table->metrics_time = jiffies; 1219 } 1220 1221 if (metrics_table) 1222 memcpy(metrics_table, smu_table->metrics_table, table_size); 1223 1224 return 0; 1225 } 1226 1227 int smu_cmn_get_combo_pptable(struct smu_context *smu) 1228 { 1229 void *pptable = smu->smu_table.combo_pptable; 1230 1231 return smu_cmn_update_table(smu, 1232 SMU_TABLE_COMBO_PPTABLE, 1233 0, 1234 pptable, 1235 false); 1236 } 1237 1238 int smu_cmn_set_mp1_state(struct smu_context *smu, 1239 enum pp_mp1_state mp1_state) 1240 { 1241 enum smu_message_type msg; 1242 int ret; 1243 1244 switch (mp1_state) { 1245 case PP_MP1_STATE_SHUTDOWN: 1246 msg = SMU_MSG_PrepareMp1ForShutdown; 1247 break; 1248 case PP_MP1_STATE_UNLOAD: 1249 msg = SMU_MSG_PrepareMp1ForUnload; 1250 break; 1251 case PP_MP1_STATE_RESET: 1252 msg = SMU_MSG_PrepareMp1ForReset; 1253 break; 1254 case PP_MP1_STATE_NONE: 1255 default: 1256 return 0; 1257 } 1258 1259 ret = smu_cmn_send_smc_msg(smu, msg, NULL); 1260 if (ret) 1261 dev_err(smu->adev->dev, "[PrepareMp1] Failed!\n"); 1262 1263 return ret; 1264 } 1265 1266 bool smu_cmn_is_audio_func_enabled(struct amdgpu_device *adev) 1267 { 1268 struct pci_dev *p = NULL; 1269 bool snd_driver_loaded; 1270 1271 /* 1272 * If the ASIC comes with no audio function, we always assume 1273 * it is "enabled". 1274 */ 1275 p = pci_get_domain_bus_and_slot(pci_domain_nr(adev->pdev->bus), 1276 adev->pdev->bus->number, 1); 1277 if (!p) 1278 return true; 1279 1280 snd_driver_loaded = pci_is_enabled(p) ? true : false; 1281 1282 pci_dev_put(p); 1283 1284 return snd_driver_loaded; 1285 } 1286 1287 static char *smu_soc_policy_get_desc(struct smu_dpm_policy *policy, int level) 1288 { 1289 if (level < 0 || !(policy->level_mask & BIT(level))) 1290 return "Invalid"; 1291 1292 switch (level) { 1293 case SOC_PSTATE_DEFAULT: 1294 return "soc_pstate_default"; 1295 case SOC_PSTATE_0: 1296 return "soc_pstate_0"; 1297 case SOC_PSTATE_1: 1298 return "soc_pstate_1"; 1299 case SOC_PSTATE_2: 1300 return "soc_pstate_2"; 1301 } 1302 1303 return "Invalid"; 1304 } 1305 1306 static struct smu_dpm_policy_desc pstate_policy_desc = { 1307 .name = STR_SOC_PSTATE_POLICY, 1308 .get_desc = smu_soc_policy_get_desc, 1309 }; 1310 1311 void smu_cmn_generic_soc_policy_desc(struct smu_dpm_policy *policy) 1312 { 1313 policy->desc = &pstate_policy_desc; 1314 } 1315 1316 static char *smu_xgmi_plpd_policy_get_desc(struct smu_dpm_policy *policy, 1317 int level) 1318 { 1319 if (level < 0 || !(policy->level_mask & BIT(level))) 1320 return "Invalid"; 1321 1322 switch (level) { 1323 case XGMI_PLPD_DISALLOW: 1324 return "plpd_disallow"; 1325 case XGMI_PLPD_DEFAULT: 1326 return "plpd_default"; 1327 case XGMI_PLPD_OPTIMIZED: 1328 return "plpd_optimized"; 1329 } 1330 1331 return "Invalid"; 1332 } 1333 1334 static struct smu_dpm_policy_desc xgmi_plpd_policy_desc = { 1335 .name = STR_XGMI_PLPD_POLICY, 1336 .get_desc = smu_xgmi_plpd_policy_get_desc, 1337 }; 1338 1339 void smu_cmn_generic_plpd_policy_desc(struct smu_dpm_policy *policy) 1340 { 1341 policy->desc = &xgmi_plpd_policy_desc; 1342 } 1343 1344 void smu_cmn_get_backend_workload_mask(struct smu_context *smu, 1345 u32 workload_mask, 1346 u32 *backend_workload_mask) 1347 { 1348 int workload_type; 1349 u32 profile_mode; 1350 1351 *backend_workload_mask = 0; 1352 1353 for (profile_mode = 0; profile_mode < PP_SMC_POWER_PROFILE_COUNT; profile_mode++) { 1354 if (!(workload_mask & (1 << profile_mode))) 1355 continue; 1356 1357 /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */ 1358 workload_type = smu_cmn_to_asic_specific_index(smu, 1359 CMN2ASIC_MAPPING_WORKLOAD, 1360 profile_mode); 1361 1362 if (workload_type < 0) 1363 continue; 1364 1365 *backend_workload_mask |= 1 << workload_type; 1366 } 1367 } 1368 1369 void smu_cmn_reset_custom_level(struct smu_context *smu) 1370 { 1371 struct smu_umd_pstate_table *pstate_table = &smu->pstate_table; 1372 1373 pstate_table->gfxclk_pstate.custom.min = 0; 1374 pstate_table->gfxclk_pstate.custom.max = 0; 1375 pstate_table->uclk_pstate.custom.min = 0; 1376 pstate_table->uclk_pstate.custom.max = 0; 1377 } 1378 1379 static inline bool smu_cmn_freqs_match(uint32_t freq1, uint32_t freq2) 1380 { 1381 /* Frequencies within 25 MHz are considered equal */ 1382 return (abs((int)freq1 - (int)freq2) <= 25); 1383 } 1384 1385 int smu_cmn_print_dpm_clk_levels(struct smu_context *smu, 1386 struct smu_dpm_table *dpm_table, 1387 uint32_t cur_clk, char *buf, int *offset) 1388 { 1389 uint32_t min_clk, max_clk, level_index, count; 1390 uint32_t freq_values[3]; 1391 int size, lvl, i; 1392 bool is_fine_grained; 1393 bool is_deep_sleep; 1394 bool freq_match; 1395 1396 if (!dpm_table || !buf) 1397 return -EINVAL; 1398 1399 level_index = 0; 1400 size = *offset; 1401 count = dpm_table->count; 1402 is_fine_grained = dpm_table->flags & SMU_DPM_TABLE_FINE_GRAINED; 1403 min_clk = SMU_DPM_TABLE_MIN(dpm_table); 1404 max_clk = SMU_DPM_TABLE_MAX(dpm_table); 1405 1406 /* Deep sleep - current clock < min_clock/2, TBD: cur_clk = 0 as GFXOFF */ 1407 is_deep_sleep = cur_clk < min_clk / 2; 1408 if (is_deep_sleep) { 1409 size += sysfs_emit_at(buf, size, "S: %uMhz *\n", cur_clk); 1410 level_index = 1; 1411 } 1412 1413 if (!is_fine_grained || count == 1) { 1414 for (i = 0; i < count; i++) { 1415 freq_match = !is_deep_sleep && 1416 smu_cmn_freqs_match( 1417 cur_clk, 1418 dpm_table->dpm_levels[i].value); 1419 size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", 1420 level_index + i, 1421 dpm_table->dpm_levels[i].value, 1422 freq_match ? "*" : ""); 1423 } 1424 } else { 1425 count = 2; 1426 freq_values[0] = min_clk; 1427 freq_values[1] = max_clk; 1428 1429 if (!is_deep_sleep) { 1430 if (smu_cmn_freqs_match(cur_clk, min_clk)) { 1431 lvl = 0; 1432 } else if (smu_cmn_freqs_match(cur_clk, max_clk)) { 1433 lvl = 1; 1434 } else { 1435 /* NOTE: use index '1' to show current clock value */ 1436 lvl = 1; 1437 count = 3; 1438 freq_values[1] = cur_clk; 1439 freq_values[2] = max_clk; 1440 } 1441 } 1442 1443 for (i = 0; i < count; i++) { 1444 size += sysfs_emit_at( 1445 buf, size, "%d: %uMhz %s\n", level_index + i, 1446 freq_values[i], 1447 (!is_deep_sleep && i == lvl) ? "*" : ""); 1448 } 1449 } 1450 1451 *offset = size; 1452 1453 return 0; 1454 } 1455 1456 int smu_cmn_print_pcie_levels(struct smu_context *smu, 1457 struct smu_pcie_table *pcie_table, 1458 uint32_t cur_gen, uint32_t cur_lane, char *buf, 1459 int *offset) 1460 { 1461 int size, i; 1462 1463 if (!pcie_table || !buf) 1464 return -EINVAL; 1465 1466 size = *offset; 1467 1468 for (i = 0; i < pcie_table->lclk_levels; i++) { 1469 size += sysfs_emit_at( 1470 buf, size, "%d: %s %s %dMhz %s\n", i, 1471 (pcie_table->pcie_gen[i] == 0) ? "2.5GT/s," : 1472 (pcie_table->pcie_gen[i] == 1) ? "5.0GT/s," : 1473 (pcie_table->pcie_gen[i] == 2) ? "8.0GT/s," : 1474 (pcie_table->pcie_gen[i] == 3) ? "16.0GT/s," : 1475 (pcie_table->pcie_gen[i] == 4) ? "32.0GT/s," : 1476 (pcie_table->pcie_gen[i] == 5) ? "64.0GT/s," : 1477 "", 1478 (pcie_table->pcie_lane[i] == 1) ? "x1" : 1479 (pcie_table->pcie_lane[i] == 2) ? "x2" : 1480 (pcie_table->pcie_lane[i] == 3) ? "x4" : 1481 (pcie_table->pcie_lane[i] == 4) ? "x8" : 1482 (pcie_table->pcie_lane[i] == 5) ? "x12" : 1483 (pcie_table->pcie_lane[i] == 6) ? "x16" : 1484 (pcie_table->pcie_lane[i] == 7) ? "x32" : 1485 "", 1486 pcie_table->lclk_freq[i], 1487 (cur_gen == pcie_table->pcie_gen[i]) && 1488 (cur_lane == pcie_table->pcie_lane[i]) ? 1489 "*" : 1490 ""); 1491 } 1492 1493 *offset = size; 1494 1495 return 0; 1496 } 1497 1498 int smu_cmn_dpm_pcie_gen_idx(int gen) 1499 { 1500 int ret; 1501 1502 switch (gen) { 1503 case 1 ... 5: 1504 ret = gen - 1; 1505 break; 1506 default: 1507 ret = -1; 1508 break; 1509 } 1510 1511 return ret; 1512 } 1513 1514 int smu_cmn_dpm_pcie_width_idx(int width) 1515 { 1516 int ret; 1517 1518 switch (width) { 1519 case 1: 1520 ret = 1; 1521 break; 1522 case 2: 1523 ret = 2; 1524 break; 1525 case 4: 1526 ret = 3; 1527 break; 1528 case 8: 1529 ret = 4; 1530 break; 1531 case 12: 1532 ret = 5; 1533 break; 1534 case 16: 1535 ret = 6; 1536 break; 1537 case 32: 1538 ret = 7; 1539 break; 1540 default: 1541 ret = -1; 1542 break; 1543 } 1544 1545 return ret; 1546 } 1547