1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2025 Intel Corporation 4 */ 5 6 #include "xe_assert.h" 7 #include "xe_device.h" 8 #include "xe_gt_sriov_pf_config.h" 9 #include "xe_sriov.h" 10 #include "xe_sriov_pf_helpers.h" 11 #include "xe_sriov_pf_provision.h" 12 #include "xe_sriov_pf_provision_types.h" 13 #include "xe_sriov_printk.h" 14 15 static const char *mode_to_string(enum xe_sriov_provisioning_mode mode) 16 { 17 switch (mode) { 18 case XE_SRIOV_PROVISIONING_MODE_AUTO: 19 return "auto"; 20 case XE_SRIOV_PROVISIONING_MODE_CUSTOM: 21 return "custom"; 22 default: 23 return "<invalid>"; 24 } 25 } 26 27 static bool pf_auto_provisioning_mode(struct xe_device *xe) 28 { 29 xe_assert(xe, IS_SRIOV_PF(xe)); 30 31 return xe->sriov.pf.provision.mode == XE_SRIOV_PROVISIONING_MODE_AUTO; 32 } 33 34 static bool pf_needs_provisioning(struct xe_gt *gt, unsigned int num_vfs) 35 { 36 unsigned int n; 37 38 for (n = 1; n <= num_vfs; n++) 39 if (!xe_gt_sriov_pf_config_is_empty(gt, n)) 40 return false; 41 42 return true; 43 } 44 45 static int pf_provision_vfs(struct xe_device *xe, unsigned int num_vfs) 46 { 47 struct xe_gt *gt; 48 unsigned int id; 49 int result = 0; 50 int err; 51 52 for_each_gt(gt, xe, id) { 53 if (!pf_needs_provisioning(gt, num_vfs)) 54 return -EUCLEAN; 55 err = xe_gt_sriov_pf_config_set_fair(gt, VFID(1), num_vfs); 56 result = result ?: err; 57 } 58 59 return result; 60 } 61 62 static void pf_unprovision_vfs(struct xe_device *xe, unsigned int num_vfs) 63 { 64 struct xe_gt *gt; 65 unsigned int id; 66 unsigned int n; 67 68 for_each_gt(gt, xe, id) 69 for (n = 1; n <= num_vfs; n++) 70 xe_gt_sriov_pf_config_release(gt, n, true); 71 } 72 73 static void pf_unprovision_all_vfs(struct xe_device *xe) 74 { 75 pf_unprovision_vfs(xe, xe_sriov_pf_get_totalvfs(xe)); 76 } 77 78 /** 79 * xe_sriov_pf_provision_vfs() - Provision VFs in auto-mode. 80 * @xe: the PF &xe_device 81 * @num_vfs: the number of VFs to auto-provision 82 * 83 * This function can only be called on PF. 84 * 85 * Return: 0 on success or a negative error code on failure. 86 */ 87 int xe_sriov_pf_provision_vfs(struct xe_device *xe, unsigned int num_vfs) 88 { 89 xe_assert(xe, IS_SRIOV_PF(xe)); 90 91 if (!pf_auto_provisioning_mode(xe)) 92 return 0; 93 94 return pf_provision_vfs(xe, num_vfs); 95 } 96 97 /** 98 * xe_sriov_pf_unprovision_vfs() - Unprovision VFs in auto-mode. 99 * @xe: the PF &xe_device 100 * @num_vfs: the number of VFs to unprovision 101 * 102 * This function can only be called on PF. 103 * 104 * Return: 0 on success or a negative error code on failure. 105 */ 106 int xe_sriov_pf_unprovision_vfs(struct xe_device *xe, unsigned int num_vfs) 107 { 108 xe_assert(xe, IS_SRIOV_PF(xe)); 109 110 if (!pf_auto_provisioning_mode(xe)) 111 return 0; 112 113 pf_unprovision_vfs(xe, num_vfs); 114 return 0; 115 } 116 117 /** 118 * xe_sriov_pf_provision_set_mode() - Change VFs provision mode. 119 * @xe: the PF &xe_device 120 * @mode: the new VFs provisioning mode 121 * 122 * When changing from AUTO to CUSTOM mode, any already allocated VFs resources 123 * will remain allocated and will not be released upon VFs disabling. 124 * 125 * When changing back to AUTO mode, if VFs are not enabled, already allocated 126 * VFs resources will be immediately released. If VFs are still enabled, such 127 * mode change is rejected. 128 * 129 * This function can only be called on PF. 130 * 131 * Return: 0 on success or a negative error code on failure. 132 */ 133 int xe_sriov_pf_provision_set_mode(struct xe_device *xe, enum xe_sriov_provisioning_mode mode) 134 { 135 xe_assert(xe, IS_SRIOV_PF(xe)); 136 137 if (mode == xe->sriov.pf.provision.mode) 138 return 0; 139 140 if (mode == XE_SRIOV_PROVISIONING_MODE_AUTO) { 141 if (xe_sriov_pf_num_vfs(xe)) { 142 xe_sriov_dbg(xe, "can't restore %s: VFs must be disabled!\n", 143 mode_to_string(mode)); 144 return -EBUSY; 145 } 146 pf_unprovision_all_vfs(xe); 147 } 148 149 xe_sriov_dbg(xe, "mode %s changed to %s by %ps\n", 150 mode_to_string(xe->sriov.pf.provision.mode), 151 mode_to_string(mode), __builtin_return_address(0)); 152 xe->sriov.pf.provision.mode = mode; 153 return 0; 154 } 155