1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2023-2024 Intel Corporation 4 */ 5 6 #include <linux/bitops.h> 7 #include <linux/pci.h> 8 9 #include "regs/xe_bars.h" 10 #include "xe_assert.h" 11 #include "xe_device.h" 12 #include "xe_gt_sriov_pf_config.h" 13 #include "xe_gt_sriov_pf_control.h" 14 #include "xe_gt_sriov_printk.h" 15 #include "xe_guc_engine_activity.h" 16 #include "xe_pci_sriov.h" 17 #include "xe_pm.h" 18 #include "xe_sriov.h" 19 #include "xe_sriov_pf.h" 20 #include "xe_sriov_pf_control.h" 21 #include "xe_sriov_pf_helpers.h" 22 #include "xe_sriov_pf_provision.h" 23 #include "xe_sriov_pf_sysfs.h" 24 #include "xe_sriov_printk.h" 25 26 static void pf_reset_vfs(struct xe_device *xe, unsigned int num_vfs) 27 { 28 unsigned int n; 29 30 for (n = 1; n <= num_vfs; n++) 31 xe_sriov_pf_control_reset_vf(xe, n); 32 } 33 34 static void pf_link_vfs(struct xe_device *xe, int num_vfs) 35 { 36 struct pci_dev *pdev_pf = to_pci_dev(xe->drm.dev); 37 struct device_link *link; 38 struct pci_dev *pdev_vf; 39 unsigned int n; 40 41 /* 42 * When both PF and VF devices are enabled on the host, during system 43 * resume they are resuming in parallel. 44 * 45 * But PF has to complete the provision of VF first to allow any VFs to 46 * successfully resume. 47 * 48 * Create a parent-child device link between PF and VF devices that will 49 * enforce correct resume order. 50 */ 51 for (n = 1; n <= num_vfs; n++) { 52 pdev_vf = xe_pci_sriov_get_vf_pdev(pdev_pf, n); 53 54 /* unlikely, something weird is happening, abort */ 55 if (!pdev_vf) { 56 xe_sriov_err(xe, "Cannot find VF%u device, aborting link%s creation!\n", 57 n, str_plural(num_vfs)); 58 break; 59 } 60 61 link = device_link_add(&pdev_vf->dev, &pdev_pf->dev, 62 DL_FLAG_AUTOREMOVE_CONSUMER); 63 /* unlikely and harmless, continue with other VFs */ 64 if (!link) 65 xe_sriov_notice(xe, "Failed linking VF%u\n", n); 66 67 pci_dev_put(pdev_vf); 68 } 69 } 70 71 static void pf_engine_activity_stats(struct xe_device *xe, unsigned int num_vfs, bool enable) 72 { 73 struct xe_gt *gt; 74 unsigned int id; 75 int ret = 0; 76 77 for_each_gt(gt, xe, id) { 78 ret = xe_guc_engine_activity_function_stats(>->uc.guc, num_vfs, enable); 79 if (ret) 80 xe_gt_sriov_info(gt, "Failed to %s engine activity function stats (%pe)\n", 81 str_enable_disable(enable), ERR_PTR(ret)); 82 } 83 } 84 85 static int resize_vf_vram_bar(struct xe_device *xe, int num_vfs) 86 { 87 struct pci_dev *pdev = to_pci_dev(xe->drm.dev); 88 u32 sizes; 89 90 sizes = pci_iov_vf_bar_get_sizes(pdev, VF_LMEM_BAR, num_vfs); 91 if (!sizes) 92 return 0; 93 94 return pci_iov_vf_bar_set_size(pdev, VF_LMEM_BAR, __fls(sizes)); 95 } 96 97 static int pf_prepare_vfs_enabling(struct xe_device *xe) 98 { 99 xe_assert(xe, IS_SRIOV_PF(xe)); 100 /* make sure we are not locked-down by other components */ 101 return xe_sriov_pf_arm_guard(xe, &xe->sriov.pf.guard_vfs_enabling, false, NULL); 102 } 103 104 static void pf_finish_vfs_enabling(struct xe_device *xe) 105 { 106 xe_assert(xe, IS_SRIOV_PF(xe)); 107 /* allow other components to lockdown VFs enabling */ 108 xe_sriov_pf_disarm_guard(xe, &xe->sriov.pf.guard_vfs_enabling, false, NULL); 109 } 110 111 static int pf_enable_vfs(struct xe_device *xe, int num_vfs) 112 { 113 struct pci_dev *pdev = to_pci_dev(xe->drm.dev); 114 int total_vfs = xe_sriov_pf_get_totalvfs(xe); 115 int err; 116 117 xe_assert(xe, IS_SRIOV_PF(xe)); 118 xe_assert(xe, num_vfs > 0); 119 xe_assert(xe, num_vfs <= total_vfs); 120 xe_sriov_dbg(xe, "enabling %u VF%s\n", num_vfs, str_plural(num_vfs)); 121 122 err = xe_sriov_pf_wait_ready(xe); 123 if (err) 124 goto out; 125 126 err = pf_prepare_vfs_enabling(xe); 127 if (err) 128 goto out; 129 130 /* 131 * We must hold additional reference to the runtime PM to keep PF in D0 132 * during VFs lifetime, as our VFs do not implement the PM capability. 133 * 134 * With PF being in D0 state, all VFs will also behave as in D0 state. 135 * This will also keep GuC alive with all VFs' configurations. 136 * 137 * We will release this additional PM reference in pf_disable_vfs(). 138 */ 139 xe_pm_runtime_get_noresume(xe); 140 141 err = xe_sriov_pf_provision_vfs(xe, num_vfs); 142 if (err < 0) 143 goto failed; 144 145 if (IS_DGFX(xe)) { 146 err = resize_vf_vram_bar(xe, num_vfs); 147 if (err) 148 xe_sriov_info(xe, "Failed to set VF LMEM BAR size: %d\n", err); 149 } 150 151 err = pci_enable_sriov(pdev, num_vfs); 152 if (err < 0) 153 goto failed; 154 155 pf_link_vfs(xe, num_vfs); 156 157 xe_sriov_info(xe, "Enabled %u of %u VF%s\n", 158 num_vfs, total_vfs, str_plural(total_vfs)); 159 160 xe_sriov_pf_sysfs_link_vfs(xe, num_vfs); 161 162 pf_engine_activity_stats(xe, num_vfs, true); 163 164 return num_vfs; 165 166 failed: 167 xe_sriov_pf_unprovision_vfs(xe, num_vfs); 168 xe_pm_runtime_put(xe); 169 pf_finish_vfs_enabling(xe); 170 out: 171 xe_sriov_notice(xe, "Failed to enable %u VF%s (%pe)\n", 172 num_vfs, str_plural(num_vfs), ERR_PTR(err)); 173 return err; 174 } 175 176 static int pf_disable_vfs(struct xe_device *xe) 177 { 178 struct device *dev = xe->drm.dev; 179 struct pci_dev *pdev = to_pci_dev(dev); 180 u16 num_vfs = pci_num_vf(pdev); 181 182 xe_assert(xe, IS_SRIOV_PF(xe)); 183 xe_sriov_dbg(xe, "disabling %u VF%s\n", num_vfs, str_plural(num_vfs)); 184 185 if (!num_vfs) 186 return 0; 187 188 pf_engine_activity_stats(xe, num_vfs, false); 189 190 xe_sriov_pf_sysfs_unlink_vfs(xe, num_vfs); 191 192 pci_disable_sriov(pdev); 193 194 pf_reset_vfs(xe, num_vfs); 195 196 xe_sriov_pf_unprovision_vfs(xe, num_vfs); 197 198 /* not needed anymore - see pf_enable_vfs() */ 199 xe_pm_runtime_put(xe); 200 201 pf_finish_vfs_enabling(xe); 202 203 xe_sriov_info(xe, "Disabled %u VF%s\n", num_vfs, str_plural(num_vfs)); 204 return 0; 205 } 206 207 /** 208 * xe_pci_sriov_configure - Configure SR-IOV (enable/disable VFs). 209 * @pdev: the &pci_dev 210 * @num_vfs: number of VFs to enable or zero to disable all VFs 211 * 212 * This is the Xe implementation of struct pci_driver.sriov_configure callback. 213 * 214 * This callback will be called by the PCI subsystem to enable or disable SR-IOV 215 * Virtual Functions (VFs) as requested by the used via the PCI sysfs interface. 216 * 217 * Return: number of configured VFs or a negative error code on failure. 218 */ 219 int xe_pci_sriov_configure(struct pci_dev *pdev, int num_vfs) 220 { 221 struct xe_device *xe = pdev_to_xe_device(pdev); 222 int ret; 223 224 if (!IS_SRIOV_PF(xe)) 225 return -ENODEV; 226 227 if (num_vfs < 0) 228 return -EINVAL; 229 230 if (num_vfs > xe_sriov_pf_get_totalvfs(xe)) 231 return -ERANGE; 232 233 if (num_vfs && pci_num_vf(pdev)) 234 return -EBUSY; 235 236 xe_pm_runtime_get(xe); 237 if (num_vfs > 0) 238 ret = pf_enable_vfs(xe, num_vfs); 239 else 240 ret = pf_disable_vfs(xe); 241 xe_pm_runtime_put(xe); 242 243 return ret; 244 } 245 246 /** 247 * xe_pci_sriov_get_vf_pdev() - Lookup the VF's PCI device using the VF identifier. 248 * @pdev: the PF's &pci_dev 249 * @vfid: VF identifier (1-based) 250 * 251 * The caller must decrement the reference count by calling pci_dev_put(). 252 * 253 * Return: the VF's &pci_dev or NULL if the VF device was not found. 254 */ 255 struct pci_dev *xe_pci_sriov_get_vf_pdev(struct pci_dev *pdev, unsigned int vfid) 256 { 257 struct xe_device *xe = pdev_to_xe_device(pdev); 258 259 xe_assert(xe, dev_is_pf(&pdev->dev)); 260 xe_assert(xe, vfid); 261 xe_assert(xe, vfid <= pci_sriov_get_totalvfs(pdev)); 262 263 return pci_get_domain_bus_and_slot(pci_domain_nr(pdev->bus), 264 pdev->bus->number, 265 pci_iov_virtfn_devfn(pdev, vfid - 1)); 266 } 267