1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2026, Advanced Micro Devices, Inc. 4 */ 5 6 #include <drm/amdxdna_accel.h> 7 #include <drm/drm_print.h> 8 #include <linux/pci.h> 9 10 #include "aie.h" 11 #include "aie4_msg_priv.h" 12 #include "aie4_pci.h" 13 #include "amdxdna_mailbox.h" 14 #include "amdxdna_mailbox_helper.h" 15 #include "amdxdna_pci_drv.h" 16 17 static int aie4_destroy_vfs(struct amdxdna_dev_hdl *ndev) 18 { 19 DECLARE_AIE_MSG(aie4_msg_destroy_vfs, AIE4_MSG_OP_DESTROY_VFS); 20 int ret; 21 22 ret = aie_send_mgmt_msg_wait(&ndev->aie, &msg); 23 if (ret) 24 XDNA_ERR(ndev->aie.xdna, "destroy vfs op failed: %d", ret); 25 26 return ret; 27 } 28 29 static int aie4_create_vfs(struct amdxdna_dev_hdl *ndev, int num_vfs) 30 { 31 DECLARE_AIE_MSG(aie4_msg_create_vfs, AIE4_MSG_OP_CREATE_VFS); 32 int ret; 33 34 req.vf_cnt = num_vfs; 35 ret = aie_send_mgmt_msg_wait(&ndev->aie, &msg); 36 if (ret) 37 XDNA_ERR(ndev->aie.xdna, "create vfs op failed: %d", ret); 38 39 return ret; 40 } 41 42 int aie4_sriov_stop(struct amdxdna_dev_hdl *ndev) 43 { 44 struct amdxdna_dev *xdna = ndev->aie.xdna; 45 struct pci_dev *pdev = to_pci_dev(xdna->ddev.dev); 46 int ret; 47 48 if (!pci_num_vf(pdev)) 49 return 0; 50 51 ret = pci_vfs_assigned(pdev); 52 if (ret) { 53 XDNA_ERR(xdna, "VFs are still assigned to VMs"); 54 return -EPERM; 55 } 56 57 pci_disable_sriov(pdev); 58 return aie4_destroy_vfs(ndev); 59 } 60 61 static int aie4_sriov_start(struct amdxdna_dev_hdl *ndev, int num_vfs) 62 { 63 struct amdxdna_dev *xdna = ndev->aie.xdna; 64 struct pci_dev *pdev = to_pci_dev(xdna->ddev.dev); 65 int ret; 66 67 ret = aie4_create_vfs(ndev, num_vfs); 68 if (ret) 69 return ret; 70 71 ret = pci_enable_sriov(pdev, num_vfs); 72 if (ret) { 73 XDNA_ERR(xdna, "configure VFs failed, ret: %d", ret); 74 aie4_destroy_vfs(ndev); 75 return ret; 76 } 77 78 return num_vfs; 79 } 80 81 int aie4_sriov_configure(struct amdxdna_dev *xdna, int num_vfs) 82 { 83 struct amdxdna_dev_hdl *ndev = xdna->dev_handle; 84 85 drm_WARN_ON(&xdna->ddev, !mutex_is_locked(&xdna->dev_lock)); 86 87 return (num_vfs) ? aie4_sriov_start(ndev, num_vfs) : aie4_sriov_stop(ndev); 88 } 89