xref: /openbmc/linux/drivers/vdpa/pds/vdpa_dev.c (revision 25d1270b6e9ea893c2fe19a4bd52ebfde22812f4)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright(c) 2023 Advanced Micro Devices, Inc */
3 
4 #include <linux/pci.h>
5 #include <linux/vdpa.h>
6 #include <uapi/linux/vdpa.h>
7 
8 #include <linux/pds/pds_common.h>
9 #include <linux/pds/pds_core_if.h>
10 #include <linux/pds/pds_adminq.h>
11 #include <linux/pds/pds_auxbus.h>
12 
13 #include "vdpa_dev.h"
14 #include "aux_drv.h"
15 
16 static struct virtio_device_id pds_vdpa_id_table[] = {
17 	{VIRTIO_ID_NET, VIRTIO_DEV_ANY_ID},
18 	{0},
19 };
20 
21 static int pds_vdpa_dev_add(struct vdpa_mgmt_dev *mdev, const char *name,
22 			    const struct vdpa_dev_set_config *add_config)
23 {
24 	return -EOPNOTSUPP;
25 }
26 
27 static void pds_vdpa_dev_del(struct vdpa_mgmt_dev *mdev,
28 			     struct vdpa_device *vdpa_dev)
29 {
30 }
31 
32 static const struct vdpa_mgmtdev_ops pds_vdpa_mgmt_dev_ops = {
33 	.dev_add = pds_vdpa_dev_add,
34 	.dev_del = pds_vdpa_dev_del
35 };
36 
37 int pds_vdpa_get_mgmt_info(struct pds_vdpa_aux *vdpa_aux)
38 {
39 	union pds_core_adminq_cmd cmd = {
40 		.vdpa_ident.opcode = PDS_VDPA_CMD_IDENT,
41 		.vdpa_ident.vf_id = cpu_to_le16(vdpa_aux->vf_id),
42 	};
43 	union pds_core_adminq_comp comp = {};
44 	struct vdpa_mgmt_dev *mgmt;
45 	struct pci_dev *pf_pdev;
46 	struct device *pf_dev;
47 	struct pci_dev *pdev;
48 	dma_addr_t ident_pa;
49 	struct device *dev;
50 	u16 dev_intrs;
51 	u16 max_vqs;
52 	int err;
53 
54 	dev = &vdpa_aux->padev->aux_dev.dev;
55 	pdev = vdpa_aux->padev->vf_pdev;
56 	mgmt = &vdpa_aux->vdpa_mdev;
57 
58 	/* Get resource info through the PF's adminq.  It is a block of info,
59 	 * so we need to map some memory for PF to make available to the
60 	 * firmware for writing the data.
61 	 */
62 	pf_pdev = pci_physfn(vdpa_aux->padev->vf_pdev);
63 	pf_dev = &pf_pdev->dev;
64 	ident_pa = dma_map_single(pf_dev, &vdpa_aux->ident,
65 				  sizeof(vdpa_aux->ident), DMA_FROM_DEVICE);
66 	if (dma_mapping_error(pf_dev, ident_pa)) {
67 		dev_err(dev, "Failed to map ident space\n");
68 		return -ENOMEM;
69 	}
70 
71 	cmd.vdpa_ident.ident_pa = cpu_to_le64(ident_pa);
72 	cmd.vdpa_ident.len = cpu_to_le32(sizeof(vdpa_aux->ident));
73 	err = pds_client_adminq_cmd(vdpa_aux->padev, &cmd,
74 				    sizeof(cmd.vdpa_ident), &comp, 0);
75 	dma_unmap_single(pf_dev, ident_pa,
76 			 sizeof(vdpa_aux->ident), DMA_FROM_DEVICE);
77 	if (err) {
78 		dev_err(dev, "Failed to ident hw, status %d: %pe\n",
79 			comp.status, ERR_PTR(err));
80 		return err;
81 	}
82 
83 	max_vqs = le16_to_cpu(vdpa_aux->ident.max_vqs);
84 	dev_intrs = pci_msix_vec_count(pdev);
85 	dev_dbg(dev, "ident.max_vqs %d dev_intrs %d\n", max_vqs, dev_intrs);
86 
87 	max_vqs = min_t(u16, dev_intrs, max_vqs);
88 	mgmt->max_supported_vqs = min_t(u16, PDS_VDPA_MAX_QUEUES, max_vqs);
89 	vdpa_aux->nintrs = mgmt->max_supported_vqs;
90 
91 	mgmt->ops = &pds_vdpa_mgmt_dev_ops;
92 	mgmt->id_table = pds_vdpa_id_table;
93 	mgmt->device = dev;
94 	mgmt->supported_features = le64_to_cpu(vdpa_aux->ident.hw_features);
95 	mgmt->config_attr_mask = BIT_ULL(VDPA_ATTR_DEV_NET_CFG_MACADDR);
96 	mgmt->config_attr_mask |= BIT_ULL(VDPA_ATTR_DEV_NET_CFG_MAX_VQP);
97 
98 	err = pci_alloc_irq_vectors(pdev, vdpa_aux->nintrs, vdpa_aux->nintrs,
99 				    PCI_IRQ_MSIX);
100 	if (err < 0) {
101 		dev_err(dev, "Couldn't get %d msix vectors: %pe\n",
102 			vdpa_aux->nintrs, ERR_PTR(err));
103 		return err;
104 	}
105 	vdpa_aux->nintrs = err;
106 
107 	return 0;
108 }
109