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