xref: /linux/drivers/accel/amdxdna/aie4_sriov.c (revision 0eaed89c18aeedf0898baf2dbf5ff027c6795152)
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