xref: /linux/drivers/gpu/drm/xe/xe_guc_rc.c (revision 0fc8f6200d2313278fbf4539bbab74677c685531)
140a684f9SVinay Belgaumkar // SPDX-License-Identifier: MIT
240a684f9SVinay Belgaumkar /*
340a684f9SVinay Belgaumkar  * Copyright © 2026 Intel Corporation
440a684f9SVinay Belgaumkar  */
540a684f9SVinay Belgaumkar 
640a684f9SVinay Belgaumkar #include <drm/drm_print.h>
740a684f9SVinay Belgaumkar 
840a684f9SVinay Belgaumkar #include "abi/guc_actions_slpc_abi.h"
940a684f9SVinay Belgaumkar #include "xe_device.h"
1040a684f9SVinay Belgaumkar #include "xe_force_wake.h"
1140a684f9SVinay Belgaumkar #include "xe_gt.h"
1240a684f9SVinay Belgaumkar #include "xe_gt_idle.h"
1340a684f9SVinay Belgaumkar #include "xe_gt_printk.h"
1440a684f9SVinay Belgaumkar #include "xe_guc.h"
1540a684f9SVinay Belgaumkar #include "xe_guc_ct.h"
16*fabedb75SVinay Belgaumkar #include "xe_guc_pc.h"
1740a684f9SVinay Belgaumkar #include "xe_guc_rc.h"
1840a684f9SVinay Belgaumkar #include "xe_pm.h"
1940a684f9SVinay Belgaumkar 
2040a684f9SVinay Belgaumkar /**
2140a684f9SVinay Belgaumkar  * DOC: GuC RC (Render C-states)
2240a684f9SVinay Belgaumkar  *
2340a684f9SVinay Belgaumkar  * GuC handles the GT transition to deeper C-states in conjunction with Pcode.
2440a684f9SVinay Belgaumkar  * GuC RC can be enabled independently of the frequency component in SLPC,
2540a684f9SVinay Belgaumkar  * which is also controlled by GuC.
2640a684f9SVinay Belgaumkar  *
2740a684f9SVinay Belgaumkar  * This file will contain all H2G related logic for handling Render C-states.
2840a684f9SVinay Belgaumkar  * There are some calls to xe_gt_idle, where we enable host C6 when GuC RC is
2940a684f9SVinay Belgaumkar  * skipped. GuC RC is mostly independent of xe_guc_pc with the exception of
3040a684f9SVinay Belgaumkar  * functions that override the mode for which we have to rely on the SLPC H2G
3140a684f9SVinay Belgaumkar  * calls.
3240a684f9SVinay Belgaumkar  */
3340a684f9SVinay Belgaumkar 
3440a684f9SVinay Belgaumkar static int guc_action_setup_gucrc(struct xe_guc *guc, u32 control)
3540a684f9SVinay Belgaumkar {
3640a684f9SVinay Belgaumkar 	u32 action[] = {
3740a684f9SVinay Belgaumkar 		GUC_ACTION_HOST2GUC_SETUP_PC_GUCRC,
3840a684f9SVinay Belgaumkar 		control,
3940a684f9SVinay Belgaumkar 	};
4040a684f9SVinay Belgaumkar 	int ret;
4140a684f9SVinay Belgaumkar 
4240a684f9SVinay Belgaumkar 	ret = xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action), 0, 0);
4340a684f9SVinay Belgaumkar 	if (ret && !(xe_device_wedged(guc_to_xe(guc)) && ret == -ECANCELED))
4440a684f9SVinay Belgaumkar 		xe_gt_err(guc_to_gt(guc),
4540a684f9SVinay Belgaumkar 			  "GuC RC setup %s(%u) failed (%pe)\n",
4640a684f9SVinay Belgaumkar 			   control == GUCRC_HOST_CONTROL ? "HOST_CONTROL" :
4740a684f9SVinay Belgaumkar 			   control == GUCRC_FIRMWARE_CONTROL ? "FIRMWARE_CONTROL" :
4840a684f9SVinay Belgaumkar 			   "UNKNOWN", control, ERR_PTR(ret));
4940a684f9SVinay Belgaumkar 	return ret;
5040a684f9SVinay Belgaumkar }
5140a684f9SVinay Belgaumkar 
5240a684f9SVinay Belgaumkar /**
5340a684f9SVinay Belgaumkar  * xe_guc_rc_disable() - Disable GuC RC
5440a684f9SVinay Belgaumkar  * @guc: Xe GuC instance
5540a684f9SVinay Belgaumkar  *
5640a684f9SVinay Belgaumkar  * Disables GuC RC by taking control of RC6 back from GuC.
5740a684f9SVinay Belgaumkar  */
5840a684f9SVinay Belgaumkar void xe_guc_rc_disable(struct xe_guc *guc)
5940a684f9SVinay Belgaumkar {
6040a684f9SVinay Belgaumkar 	struct xe_device *xe = guc_to_xe(guc);
6140a684f9SVinay Belgaumkar 	struct xe_gt *gt = guc_to_gt(guc);
6240a684f9SVinay Belgaumkar 
6340a684f9SVinay Belgaumkar 	if (!xe->info.skip_guc_pc && xe->info.platform != XE_PVC)
6440a684f9SVinay Belgaumkar 		if (guc_action_setup_gucrc(guc, GUCRC_HOST_CONTROL))
6540a684f9SVinay Belgaumkar 			return;
6640a684f9SVinay Belgaumkar 
6740a684f9SVinay Belgaumkar 	xe_gt_WARN_ON(gt, xe_gt_idle_disable_c6(gt));
6840a684f9SVinay Belgaumkar }
6940a684f9SVinay Belgaumkar 
7040a684f9SVinay Belgaumkar static void xe_guc_rc_fini_hw(void *arg)
7140a684f9SVinay Belgaumkar {
7240a684f9SVinay Belgaumkar 	struct xe_guc *guc = arg;
7340a684f9SVinay Belgaumkar 	struct xe_device *xe = guc_to_xe(guc);
7440a684f9SVinay Belgaumkar 	struct xe_gt *gt = guc_to_gt(guc);
7540a684f9SVinay Belgaumkar 
7640a684f9SVinay Belgaumkar 	if (xe_device_wedged(xe))
7740a684f9SVinay Belgaumkar 		return;
7840a684f9SVinay Belgaumkar 
7940a684f9SVinay Belgaumkar 	CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT);
8040a684f9SVinay Belgaumkar 	xe_guc_rc_disable(guc);
8140a684f9SVinay Belgaumkar }
8240a684f9SVinay Belgaumkar 
8340a684f9SVinay Belgaumkar /**
8440a684f9SVinay Belgaumkar  * xe_guc_rc_init() - Init GuC RC
8540a684f9SVinay Belgaumkar  * @guc: Xe GuC instance
8640a684f9SVinay Belgaumkar  *
8740a684f9SVinay Belgaumkar  * Add callback action for GuC RC
8840a684f9SVinay Belgaumkar  *
8940a684f9SVinay Belgaumkar  * Return: 0 on success, negative error code on error.
9040a684f9SVinay Belgaumkar  */
9140a684f9SVinay Belgaumkar int xe_guc_rc_init(struct xe_guc *guc)
9240a684f9SVinay Belgaumkar {
9340a684f9SVinay Belgaumkar 	struct xe_device *xe = guc_to_xe(guc);
9440a684f9SVinay Belgaumkar 	struct xe_gt *gt = guc_to_gt(guc);
9540a684f9SVinay Belgaumkar 
9640a684f9SVinay Belgaumkar 	xe_gt_assert(gt, xe_device_uc_enabled(xe));
9740a684f9SVinay Belgaumkar 
9840a684f9SVinay Belgaumkar 	return devm_add_action_or_reset(xe->drm.dev, xe_guc_rc_fini_hw, guc);
9940a684f9SVinay Belgaumkar }
10040a684f9SVinay Belgaumkar 
10140a684f9SVinay Belgaumkar /**
10240a684f9SVinay Belgaumkar  * xe_guc_rc_enable() - Enable GuC RC feature if applicable
10340a684f9SVinay Belgaumkar  * @guc: Xe GuC instance
10440a684f9SVinay Belgaumkar  *
10540a684f9SVinay Belgaumkar  * Enables GuC RC feature.
10640a684f9SVinay Belgaumkar  *
10740a684f9SVinay Belgaumkar  * Return: 0 on success, negative error code on error.
10840a684f9SVinay Belgaumkar  */
10940a684f9SVinay Belgaumkar int xe_guc_rc_enable(struct xe_guc *guc)
11040a684f9SVinay Belgaumkar {
11140a684f9SVinay Belgaumkar 	struct xe_device *xe = guc_to_xe(guc);
11240a684f9SVinay Belgaumkar 	struct xe_gt *gt = guc_to_gt(guc);
11340a684f9SVinay Belgaumkar 
11440a684f9SVinay Belgaumkar 	xe_gt_assert(gt, xe_device_uc_enabled(xe));
11540a684f9SVinay Belgaumkar 
11640a684f9SVinay Belgaumkar 	CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FW_GT);
11740a684f9SVinay Belgaumkar 	if (!xe_force_wake_ref_has_domain(fw_ref.domains, XE_FW_GT))
11840a684f9SVinay Belgaumkar 		return -ETIMEDOUT;
11940a684f9SVinay Belgaumkar 
12040a684f9SVinay Belgaumkar 	if (xe->info.platform == XE_PVC) {
12140a684f9SVinay Belgaumkar 		xe_guc_rc_disable(guc);
12240a684f9SVinay Belgaumkar 		return 0;
12340a684f9SVinay Belgaumkar 	}
12440a684f9SVinay Belgaumkar 
12540a684f9SVinay Belgaumkar 	if (xe->info.skip_guc_pc) {
12640a684f9SVinay Belgaumkar 		xe_gt_idle_enable_c6(gt);
12740a684f9SVinay Belgaumkar 		return 0;
12840a684f9SVinay Belgaumkar 	}
12940a684f9SVinay Belgaumkar 
13040a684f9SVinay Belgaumkar 	return guc_action_setup_gucrc(guc, GUCRC_FIRMWARE_CONTROL);
13140a684f9SVinay Belgaumkar }
132