1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2023-2024 Intel Corporation 4 */ 5 6 #include "abi/guc_actions_sriov_abi.h" 7 8 #include "xe_bo.h" 9 #include "xe_gt.h" 10 #include "xe_gt_sriov_pf_helpers.h" 11 #include "xe_gt_sriov_pf_policy.h" 12 #include "xe_gt_sriov_printk.h" 13 #include "xe_guc_ct.h" 14 #include "xe_guc_klv_helpers.h" 15 #include "xe_pm.h" 16 17 /* 18 * Return: number of KLVs that were successfully parsed and saved, 19 * negative error code on failure. 20 */ 21 static int guc_action_update_vgt_policy(struct xe_guc *guc, u64 addr, u32 size) 22 { 23 u32 request[] = { 24 GUC_ACTION_PF2GUC_UPDATE_VGT_POLICY, 25 lower_32_bits(addr), 26 upper_32_bits(addr), 27 size, 28 }; 29 30 return xe_guc_ct_send_block(&guc->ct, request, ARRAY_SIZE(request)); 31 } 32 33 /* 34 * Return: number of KLVs that were successfully parsed and saved, 35 * negative error code on failure. 36 */ 37 static int pf_send_policy_klvs(struct xe_gt *gt, const u32 *klvs, u32 num_dwords) 38 { 39 const u32 bytes = num_dwords * sizeof(u32); 40 struct xe_tile *tile = gt_to_tile(gt); 41 struct xe_device *xe = tile_to_xe(tile); 42 struct xe_guc *guc = >->uc.guc; 43 struct xe_bo *bo; 44 int ret; 45 46 bo = xe_bo_create_pin_map(xe, tile, NULL, 47 ALIGN(bytes, PAGE_SIZE), 48 ttm_bo_type_kernel, 49 XE_BO_FLAG_VRAM_IF_DGFX(tile) | 50 XE_BO_FLAG_GGTT); 51 if (IS_ERR(bo)) 52 return PTR_ERR(bo); 53 54 xe_map_memcpy_to(xe, &bo->vmap, 0, klvs, bytes); 55 56 ret = guc_action_update_vgt_policy(guc, xe_bo_ggtt_addr(bo), num_dwords); 57 58 xe_bo_unpin_map_no_vm(bo); 59 60 return ret; 61 } 62 63 /* 64 * Return: 0 on success, -ENOKEY if some KLVs were not updated, -EPROTO if reply was malformed, 65 * negative error code on failure. 66 */ 67 static int pf_push_policy_klvs(struct xe_gt *gt, u32 num_klvs, 68 const u32 *klvs, u32 num_dwords) 69 { 70 int ret; 71 72 xe_gt_assert(gt, num_klvs == xe_guc_klv_count(klvs, num_dwords)); 73 74 ret = pf_send_policy_klvs(gt, klvs, num_dwords); 75 76 if (ret != num_klvs) { 77 int err = ret < 0 ? ret : ret < num_klvs ? -ENOKEY : -EPROTO; 78 struct drm_printer p = xe_gt_info_printer(gt); 79 80 xe_gt_sriov_notice(gt, "Failed to push %u policy KLV%s (%pe)\n", 81 num_klvs, str_plural(num_klvs), ERR_PTR(err)); 82 xe_guc_klv_print(klvs, num_dwords, &p); 83 return err; 84 } 85 86 return 0; 87 } 88 89 static int pf_push_policy_u32(struct xe_gt *gt, u16 key, u32 value) 90 { 91 u32 klv[] = { 92 PREP_GUC_KLV(key, 1), 93 value, 94 }; 95 96 return pf_push_policy_klvs(gt, 1, klv, ARRAY_SIZE(klv)); 97 } 98 99 static int pf_update_policy_bool(struct xe_gt *gt, u16 key, bool *policy, bool value) 100 { 101 int err; 102 103 err = pf_push_policy_u32(gt, key, value); 104 if (unlikely(err)) { 105 xe_gt_sriov_notice(gt, "Failed to update policy %#x '%s' to '%s' (%pe)\n", 106 key, xe_guc_klv_key_to_string(key), 107 str_enabled_disabled(value), ERR_PTR(err)); 108 return err; 109 } 110 111 xe_gt_sriov_dbg(gt, "policy key %#x '%s' updated to '%s'\n", 112 key, xe_guc_klv_key_to_string(key), 113 str_enabled_disabled(value)); 114 115 *policy = value; 116 return 0; 117 } 118 119 static int pf_update_policy_u32(struct xe_gt *gt, u16 key, u32 *policy, u32 value) 120 { 121 int err; 122 123 err = pf_push_policy_u32(gt, key, value); 124 if (unlikely(err)) { 125 xe_gt_sriov_notice(gt, "Failed to update policy %#x '%s' to '%s' (%pe)\n", 126 key, xe_guc_klv_key_to_string(key), 127 str_enabled_disabled(value), ERR_PTR(err)); 128 return err; 129 } 130 131 xe_gt_sriov_dbg(gt, "policy key %#x '%s' updated to %u\n", 132 key, xe_guc_klv_key_to_string(key), value); 133 134 *policy = value; 135 return 0; 136 } 137 138 static int pf_provision_sched_if_idle(struct xe_gt *gt, bool enable) 139 { 140 xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt))); 141 lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); 142 143 return pf_update_policy_bool(gt, GUC_KLV_VGT_POLICY_SCHED_IF_IDLE_KEY, 144 >->sriov.pf.policy.guc.sched_if_idle, 145 enable); 146 } 147 148 static int pf_reprovision_sched_if_idle(struct xe_gt *gt) 149 { 150 xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt))); 151 lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); 152 153 return pf_provision_sched_if_idle(gt, gt->sriov.pf.policy.guc.sched_if_idle); 154 } 155 156 static void pf_sanitize_sched_if_idle(struct xe_gt *gt) 157 { 158 xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt))); 159 lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); 160 161 gt->sriov.pf.policy.guc.sched_if_idle = false; 162 } 163 164 /** 165 * xe_gt_sriov_pf_policy_set_sched_if_idle - Control the 'sched_if_idle' policy. 166 * @gt: the &xe_gt where to apply the policy 167 * @enable: the value of the 'sched_if_idle' policy 168 * 169 * This function can only be called on PF. 170 * 171 * Return: 0 on success or a negative error code on failure. 172 */ 173 int xe_gt_sriov_pf_policy_set_sched_if_idle(struct xe_gt *gt, bool enable) 174 { 175 int err; 176 177 mutex_lock(xe_gt_sriov_pf_master_mutex(gt)); 178 err = pf_provision_sched_if_idle(gt, enable); 179 mutex_unlock(xe_gt_sriov_pf_master_mutex(gt)); 180 181 return err; 182 } 183 184 /** 185 * xe_gt_sriov_pf_policy_get_sched_if_idle - Retrieve value of 'sched_if_idle' policy. 186 * @gt: the &xe_gt where to read the policy from 187 * 188 * This function can only be called on PF. 189 * 190 * Return: value of 'sched_if_idle' policy. 191 */ 192 bool xe_gt_sriov_pf_policy_get_sched_if_idle(struct xe_gt *gt) 193 { 194 bool enable; 195 196 xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt))); 197 198 mutex_lock(xe_gt_sriov_pf_master_mutex(gt)); 199 enable = gt->sriov.pf.policy.guc.sched_if_idle; 200 mutex_unlock(xe_gt_sriov_pf_master_mutex(gt)); 201 202 return enable; 203 } 204 205 static int pf_provision_reset_engine(struct xe_gt *gt, bool enable) 206 { 207 xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt))); 208 lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); 209 210 return pf_update_policy_bool(gt, GUC_KLV_VGT_POLICY_RESET_AFTER_VF_SWITCH_KEY, 211 >->sriov.pf.policy.guc.reset_engine, enable); 212 } 213 214 static int pf_reprovision_reset_engine(struct xe_gt *gt) 215 { 216 xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt))); 217 lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); 218 219 return pf_provision_reset_engine(gt, gt->sriov.pf.policy.guc.reset_engine); 220 } 221 222 static void pf_sanitize_reset_engine(struct xe_gt *gt) 223 { 224 xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt))); 225 lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); 226 227 gt->sriov.pf.policy.guc.reset_engine = false; 228 } 229 230 /** 231 * xe_gt_sriov_pf_policy_set_reset_engine - Control the 'reset_engine' policy. 232 * @gt: the &xe_gt where to apply the policy 233 * @enable: the value of the 'reset_engine' policy 234 * 235 * This function can only be called on PF. 236 * 237 * Return: 0 on success or a negative error code on failure. 238 */ 239 int xe_gt_sriov_pf_policy_set_reset_engine(struct xe_gt *gt, bool enable) 240 { 241 int err; 242 243 mutex_lock(xe_gt_sriov_pf_master_mutex(gt)); 244 err = pf_provision_reset_engine(gt, enable); 245 mutex_unlock(xe_gt_sriov_pf_master_mutex(gt)); 246 247 return err; 248 } 249 250 /** 251 * xe_gt_sriov_pf_policy_get_reset_engine - Retrieve value of 'reset_engine' policy. 252 * @gt: the &xe_gt where to read the policy from 253 * 254 * This function can only be called on PF. 255 * 256 * Return: value of 'reset_engine' policy. 257 */ 258 bool xe_gt_sriov_pf_policy_get_reset_engine(struct xe_gt *gt) 259 { 260 bool enable; 261 262 xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt))); 263 264 mutex_lock(xe_gt_sriov_pf_master_mutex(gt)); 265 enable = gt->sriov.pf.policy.guc.reset_engine; 266 mutex_unlock(xe_gt_sriov_pf_master_mutex(gt)); 267 268 return enable; 269 } 270 271 static int pf_provision_sample_period(struct xe_gt *gt, u32 value) 272 { 273 xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt))); 274 lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); 275 276 return pf_update_policy_u32(gt, GUC_KLV_VGT_POLICY_ADVERSE_SAMPLE_PERIOD_KEY, 277 >->sriov.pf.policy.guc.sample_period, value); 278 } 279 280 static int pf_reprovision_sample_period(struct xe_gt *gt) 281 { 282 xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt))); 283 lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); 284 285 return pf_provision_sample_period(gt, gt->sriov.pf.policy.guc.sample_period); 286 } 287 288 static void pf_sanitize_sample_period(struct xe_gt *gt) 289 { 290 xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt))); 291 lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt)); 292 293 gt->sriov.pf.policy.guc.sample_period = 0; 294 } 295 296 /** 297 * xe_gt_sriov_pf_policy_set_sample_period - Control the 'sample_period' policy. 298 * @gt: the &xe_gt where to apply the policy 299 * @value: the value of the 'sample_period' policy 300 * 301 * This function can only be called on PF. 302 * 303 * Return: 0 on success or a negative error code on failure. 304 */ 305 int xe_gt_sriov_pf_policy_set_sample_period(struct xe_gt *gt, u32 value) 306 { 307 int err; 308 309 mutex_lock(xe_gt_sriov_pf_master_mutex(gt)); 310 err = pf_provision_sample_period(gt, value); 311 mutex_unlock(xe_gt_sriov_pf_master_mutex(gt)); 312 313 return err; 314 } 315 316 /** 317 * xe_gt_sriov_pf_policy_get_sample_period - Retrieve value of 'sample_period' policy. 318 * @gt: the &xe_gt where to read the policy from 319 * 320 * This function can only be called on PF. 321 * 322 * Return: value of 'sample_period' policy. 323 */ 324 u32 xe_gt_sriov_pf_policy_get_sample_period(struct xe_gt *gt) 325 { 326 u32 value; 327 328 xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt))); 329 330 mutex_lock(xe_gt_sriov_pf_master_mutex(gt)); 331 value = gt->sriov.pf.policy.guc.sample_period; 332 mutex_unlock(xe_gt_sriov_pf_master_mutex(gt)); 333 334 return value; 335 } 336 337 static void pf_sanitize_guc_policies(struct xe_gt *gt) 338 { 339 pf_sanitize_sched_if_idle(gt); 340 pf_sanitize_reset_engine(gt); 341 pf_sanitize_sample_period(gt); 342 } 343 344 /** 345 * xe_gt_sriov_pf_policy_sanitize - Reset policy settings. 346 * @gt: the &xe_gt 347 * 348 * This function can only be called on PF. 349 * 350 * Return: 0 on success or a negative error code on failure. 351 */ 352 void xe_gt_sriov_pf_policy_sanitize(struct xe_gt *gt) 353 { 354 mutex_lock(xe_gt_sriov_pf_master_mutex(gt)); 355 pf_sanitize_guc_policies(gt); 356 mutex_unlock(xe_gt_sriov_pf_master_mutex(gt)); 357 } 358 359 /** 360 * xe_gt_sriov_pf_policy_reprovision - Reprovision (and optionally reset) policy settings. 361 * @gt: the &xe_gt 362 * @reset: if true will reprovision using default values instead of latest 363 * 364 * This function can only be called on PF. 365 * 366 * Return: 0 on success or a negative error code on failure. 367 */ 368 int xe_gt_sriov_pf_policy_reprovision(struct xe_gt *gt, bool reset) 369 { 370 int err = 0; 371 372 xe_pm_runtime_get_noresume(gt_to_xe(gt)); 373 374 mutex_lock(xe_gt_sriov_pf_master_mutex(gt)); 375 if (reset) 376 pf_sanitize_guc_policies(gt); 377 err |= pf_reprovision_sched_if_idle(gt); 378 err |= pf_reprovision_reset_engine(gt); 379 err |= pf_reprovision_sample_period(gt); 380 mutex_unlock(xe_gt_sriov_pf_master_mutex(gt)); 381 382 xe_pm_runtime_put(gt_to_xe(gt)); 383 384 return err ? -ENXIO : 0; 385 } 386 387 static void print_guc_policies(struct drm_printer *p, struct xe_gt_sriov_guc_policies *policy) 388 { 389 drm_printf(p, "%s:\t%s\n", 390 xe_guc_klv_key_to_string(GUC_KLV_VGT_POLICY_SCHED_IF_IDLE_KEY), 391 str_enabled_disabled(policy->sched_if_idle)); 392 drm_printf(p, "%s:\t%s\n", 393 xe_guc_klv_key_to_string(GUC_KLV_VGT_POLICY_RESET_AFTER_VF_SWITCH_KEY), 394 str_enabled_disabled(policy->reset_engine)); 395 drm_printf(p, "%s:\t%u %s\n", 396 xe_guc_klv_key_to_string(GUC_KLV_VGT_POLICY_ADVERSE_SAMPLE_PERIOD_KEY), 397 policy->sample_period, policy->sample_period ? "ms" : "(disabled)"); 398 } 399 400 /** 401 * xe_gt_sriov_pf_policy_print - Dump actual policy values. 402 * @gt: the &xe_gt where to read the policy from 403 * @p: the &drm_printer 404 * 405 * This function can only be called on PF. 406 * 407 * Return: 0 on success or a negative error code on failure. 408 */ 409 int xe_gt_sriov_pf_policy_print(struct xe_gt *gt, struct drm_printer *p) 410 { 411 xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt))); 412 413 mutex_lock(xe_gt_sriov_pf_master_mutex(gt)); 414 print_guc_policies(p, >->sriov.pf.policy.guc); 415 mutex_unlock(xe_gt_sriov_pf_master_mutex(gt)); 416 417 return 0; 418 } 419