Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/xe/guc: Update handling of xe_force_wake_get return

xe_force_wake_get() now returns the reference count-incremented domain
mask. If it fails for individual domains, the return value will always
be 0. However, for XE_FORCEWAKE_ALL, it may return a non-zero value even
in the event of failure. Use helper xe_force_wake_ref_has_domain to
verify all domains are initialized or not. Update the return handling of
xe_force_wake_get() to reflect this behavior, and ensure that the return
value is passed as input to xe_force_wake_put().

v3
- return xe_wakeref_t instead of int in xe_force_wake_get()
- xe_force_wake_put() error doesn't need to be checked. It internally
WARNS on domain ack failure.

v5
- return unsigned int from xe_force_wake_get()
- Remove redundant xe_gt_WARN_ON

v6
- use helper xe_force_wake_ref_has_domain()

v7
- Fix commit message

v9
- Rebase

Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Lucas De Marchi <lucas.demarchi@intel.com>
Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
Reviewed-by: Nirmoy Das <nirmoy.das@intel.com>
Reviewed-by: Badal Nilawar <badal.nilawar@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20241014075601.2324382-17-himal.prasad.ghimiray@intel.com
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>

authored by

Himal Prasad Ghimiray and committed by
Rodrigo Vivi
31a5dce0 85d54760

+47 -31
+7 -6
drivers/gpu/drm/xe/xe_guc.c
··· 248 248 { 249 249 struct xe_guc *guc = arg; 250 250 struct xe_gt *gt = guc_to_gt(guc); 251 + unsigned int fw_ref; 251 252 252 - xe_gt_WARN_ON(gt, xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL)); 253 + fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL); 253 254 xe_uc_fini_hw(&guc_to_gt(guc)->uc); 254 - xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL); 255 + xe_force_wake_put(gt_to_fw(gt), fw_ref); 255 256 } 256 257 257 258 /** ··· 1156 1155 void xe_guc_print_info(struct xe_guc *guc, struct drm_printer *p) 1157 1156 { 1158 1157 struct xe_gt *gt = guc_to_gt(guc); 1158 + unsigned int fw_ref; 1159 1159 u32 status; 1160 - int err; 1161 1160 int i; 1162 1161 1163 1162 xe_uc_fw_print(&guc->fw, p); 1164 1163 1165 - err = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); 1166 - if (err) 1164 + fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); 1165 + if (!fw_ref) 1167 1166 return; 1168 1167 1169 1168 status = xe_mmio_read32(&gt->mmio, GUC_STATUS); ··· 1184 1183 i, xe_mmio_read32(&gt->mmio, SOFT_SCRATCH(i))); 1185 1184 } 1186 1185 1187 - xe_force_wake_put(gt_to_fw(gt), XE_FW_GT); 1186 + xe_force_wake_put(gt_to_fw(gt), fw_ref); 1188 1187 1189 1188 xe_guc_ct_print(&guc->ct, p); 1190 1189 xe_guc_submit_print(guc, p);
+5 -4
drivers/gpu/drm/xe/xe_guc_log.c
··· 145 145 struct xe_device *xe = log_to_xe(log); 146 146 struct xe_guc *guc = log_to_guc(log); 147 147 struct xe_gt *gt = log_to_gt(log); 148 + unsigned int fw_ref; 148 149 size_t remain; 149 - int i, err; 150 + int i; 150 151 151 152 if (!log->bo) { 152 153 xe_gt_err(gt, "GuC log buffer not allocated\n"); ··· 169 168 remain -= size; 170 169 } 171 170 172 - err = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); 173 - if (err) { 171 + fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); 172 + if (!fw_ref) { 174 173 snapshot->stamp = ~0; 175 174 } else { 176 175 snapshot->stamp = xe_mmio_read32(&gt->mmio, GUC_PMTIMESTAMP); 177 - xe_force_wake_put(gt_to_fw(gt), XE_FW_GT); 176 + xe_force_wake_put(gt_to_fw(gt), fw_ref); 178 177 } 179 178 snapshot->ktime = ktime_get_boottime_ns(); 180 179 snapshot->level = log->level;
+31 -19
drivers/gpu/drm/xe/xe_guc_pc.c
··· 415 415 int xe_guc_pc_get_cur_freq(struct xe_guc_pc *pc, u32 *freq) 416 416 { 417 417 struct xe_gt *gt = pc_to_gt(pc); 418 - int ret; 418 + unsigned int fw_ref; 419 419 420 420 /* 421 421 * GuC SLPC plays with cur freq request when GuCRC is enabled 422 422 * Block RC6 for a more reliable read. 423 423 */ 424 - ret = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL); 425 - if (ret) 426 - return ret; 424 + fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL); 425 + if (!xe_force_wake_ref_has_domain(fw_ref, XE_FORCEWAKE_ALL)) { 426 + xe_force_wake_put(gt_to_fw(gt), fw_ref); 427 + return -ETIMEDOUT; 428 + } 427 429 428 430 *freq = xe_mmio_read32(&gt->mmio, RPNSWREQ); 429 431 430 432 *freq = REG_FIELD_GET(REQ_RATIO_MASK, *freq); 431 433 *freq = decode_freq(*freq); 432 434 433 - XE_WARN_ON(xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL)); 435 + xe_force_wake_put(gt_to_fw(gt), fw_ref); 434 436 return 0; 435 437 } 436 438 ··· 482 480 int xe_guc_pc_get_min_freq(struct xe_guc_pc *pc, u32 *freq) 483 481 { 484 482 struct xe_gt *gt = pc_to_gt(pc); 483 + unsigned int fw_ref; 485 484 int ret; 486 485 487 486 mutex_lock(&pc->freq_lock); ··· 496 493 * GuC SLPC plays with min freq request when GuCRC is enabled 497 494 * Block RC6 for a more reliable read. 498 495 */ 499 - ret = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL); 500 - if (ret) 501 - goto out; 496 + fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL); 497 + if (!xe_force_wake_ref_has_domain(fw_ref, XE_FORCEWAKE_ALL)) { 498 + ret = -ETIMEDOUT; 499 + goto fw; 500 + } 502 501 503 502 ret = pc_action_query_task_state(pc); 504 503 if (ret) ··· 509 504 *freq = pc_get_min_freq(pc); 510 505 511 506 fw: 512 - XE_WARN_ON(xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL)); 507 + xe_force_wake_put(gt_to_fw(gt), fw_ref); 513 508 out: 514 509 mutex_unlock(&pc->freq_lock); 515 510 return ret; ··· 860 855 { 861 856 struct xe_device *xe = pc_to_xe(pc); 862 857 struct xe_gt *gt = pc_to_gt(pc); 858 + unsigned int fw_ref; 863 859 int ret = 0; 864 860 865 861 if (xe->info.skip_guc_pc) ··· 870 864 if (ret) 871 865 return ret; 872 866 873 - ret = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL); 874 - if (ret) 875 - return ret; 867 + fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL); 868 + if (!xe_force_wake_ref_has_domain(fw_ref, XE_FORCEWAKE_ALL)) { 869 + xe_force_wake_put(gt_to_fw(gt), fw_ref); 870 + return -ETIMEDOUT; 871 + } 876 872 877 873 xe_gt_idle_disable_c6(gt); 878 874 879 - XE_WARN_ON(xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL)); 875 + xe_force_wake_put(gt_to_fw(gt), fw_ref); 880 876 881 877 return 0; 882 878 } ··· 964 956 struct xe_device *xe = pc_to_xe(pc); 965 957 struct xe_gt *gt = pc_to_gt(pc); 966 958 u32 size = PAGE_ALIGN(sizeof(struct slpc_shared_data)); 959 + unsigned int fw_ref; 967 960 int ret; 968 961 969 962 xe_gt_assert(gt, xe_device_uc_enabled(xe)); 970 963 971 - ret = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL); 972 - if (ret) 973 - return ret; 964 + fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL); 965 + if (!xe_force_wake_ref_has_domain(fw_ref, XE_FORCEWAKE_ALL)) { 966 + xe_force_wake_put(gt_to_fw(gt), fw_ref); 967 + return -ETIMEDOUT; 968 + } 974 969 975 970 if (xe->info.skip_guc_pc) { 976 971 if (xe->info.platform != XE_PVC) ··· 1016 1005 ret = pc_action_setup_gucrc(pc, GUCRC_FIRMWARE_CONTROL); 1017 1006 1018 1007 out: 1019 - XE_WARN_ON(xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL)); 1008 + xe_force_wake_put(gt_to_fw(gt), fw_ref); 1020 1009 return ret; 1021 1010 } 1022 1011 ··· 1048 1037 { 1049 1038 struct xe_guc_pc *pc = arg; 1050 1039 struct xe_device *xe = pc_to_xe(pc); 1040 + unsigned int fw_ref; 1051 1041 1052 1042 if (xe_device_wedged(xe)) 1053 1043 return; 1054 1044 1055 - XE_WARN_ON(xe_force_wake_get(gt_to_fw(pc_to_gt(pc)), XE_FORCEWAKE_ALL)); 1045 + fw_ref = xe_force_wake_get(gt_to_fw(pc_to_gt(pc)), XE_FORCEWAKE_ALL); 1056 1046 xe_guc_pc_gucrc_disable(pc); 1057 1047 XE_WARN_ON(xe_guc_pc_stop(pc)); 1058 1048 1059 1049 /* Bind requested freq to mert_freq_cap before unload */ 1060 1050 pc_set_cur_freq(pc, min(pc_max_freq_cap(pc), pc->rpe_freq)); 1061 1051 1062 - xe_force_wake_put(gt_to_fw(pc_to_gt(pc)), XE_FORCEWAKE_ALL); 1052 + xe_force_wake_put(gt_to_fw(pc_to_gt(pc)), fw_ref); 1063 1053 } 1064 1054 1065 1055 /**
+4 -2
drivers/gpu/drm/xe/xe_guc_submit.c
··· 1098 1098 struct xe_guc *guc = exec_queue_to_guc(q); 1099 1099 const char *process_name = "no process"; 1100 1100 struct xe_device *xe = guc_to_xe(guc); 1101 + unsigned int fw_ref; 1101 1102 int err = -ETIME; 1102 1103 pid_t pid = -1; 1103 1104 int i = 0; ··· 1136 1135 if (!exec_queue_killed(q) && !xe->devcoredump.captured && 1137 1136 !xe_guc_capture_get_matching_and_lock(job)) { 1138 1137 /* take force wake before engine register manual capture */ 1139 - if (xe_force_wake_get(gt_to_fw(q->gt), XE_FORCEWAKE_ALL)) 1138 + fw_ref = xe_force_wake_get(gt_to_fw(q->gt), XE_FORCEWAKE_ALL); 1139 + if (!xe_force_wake_ref_has_domain(fw_ref, XE_FORCEWAKE_ALL)) 1140 1140 xe_gt_info(q->gt, "failed to get forcewake for coredump capture\n"); 1141 1141 1142 1142 xe_engine_snapshot_capture_for_job(job); 1143 1143 1144 - xe_force_wake_put(gt_to_fw(q->gt), XE_FORCEWAKE_ALL); 1144 + xe_force_wake_put(gt_to_fw(q->gt), fw_ref); 1145 1145 } 1146 1146 1147 1147 /*