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