1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2021 Intel Corporation
4  */
5 
6 #include <linux/string_helpers.h>
7 
8 #include "intel_guc_rc.h"
9 #include "gt/intel_gt.h"
10 #include "i915_drv.h"
11 
12 static bool __guc_rc_supported(struct intel_guc *guc)
13 {
14 	struct intel_gt *gt = guc_to_gt(guc);
15 
16 	/*
17 	 * Wa_14017073508: mtl
18 	 * Do not enable gucrc to avoid additional interrupts which
19 	 * may disrupt pcode wa.
20 	 */
21 	if (IS_MTL_GRAPHICS_STEP(gt->i915, P, STEP_A0, STEP_B0) &&
22 	    gt->type == GT_MEDIA)
23 		return false;
24 
25 	/* GuC RC is unavailable for pre-Gen12 */
26 	return guc->submission_supported &&
27 		GRAPHICS_VER(gt->i915) >= 12;
28 }
29 
30 static bool __guc_rc_selected(struct intel_guc *guc)
31 {
32 	if (!intel_guc_rc_is_supported(guc))
33 		return false;
34 
35 	return guc->submission_selected;
36 }
37 
38 void intel_guc_rc_init_early(struct intel_guc *guc)
39 {
40 	guc->rc_supported = __guc_rc_supported(guc);
41 	guc->rc_selected = __guc_rc_selected(guc);
42 }
43 
44 static int guc_action_control_gucrc(struct intel_guc *guc, bool enable)
45 {
46 	u32 rc_mode = enable ? INTEL_GUCRC_FIRMWARE_CONTROL :
47 				INTEL_GUCRC_HOST_CONTROL;
48 	u32 action[] = {
49 		INTEL_GUC_ACTION_SETUP_PC_GUCRC,
50 		rc_mode
51 	};
52 	int ret;
53 
54 	ret = intel_guc_send(guc, action, ARRAY_SIZE(action));
55 	ret = ret > 0 ? -EPROTO : ret;
56 
57 	return ret;
58 }
59 
60 static int __guc_rc_control(struct intel_guc *guc, bool enable)
61 {
62 	struct intel_gt *gt = guc_to_gt(guc);
63 	int ret;
64 
65 	if (!intel_uc_uses_guc_rc(&gt->uc))
66 		return -EOPNOTSUPP;
67 
68 	if (!intel_guc_is_ready(guc))
69 		return -EINVAL;
70 
71 	ret = guc_action_control_gucrc(guc, enable);
72 	if (ret) {
73 		i915_probe_error(guc_to_gt(guc)->i915, "Failed to %s GuC RC (%pe)\n",
74 				 str_enable_disable(enable), ERR_PTR(ret));
75 		return ret;
76 	}
77 
78 	drm_info(&gt->i915->drm, "GuC RC: %s\n",
79 		 str_enabled_disabled(enable));
80 
81 	return 0;
82 }
83 
84 int intel_guc_rc_enable(struct intel_guc *guc)
85 {
86 	return __guc_rc_control(guc, true);
87 }
88 
89 int intel_guc_rc_disable(struct intel_guc *guc)
90 {
91 	return __guc_rc_control(guc, false);
92 }
93