1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2017 Cavium, Inc 3 */ 4 5 #include <rte_eal.h> 6 #include <rte_io.h> 7 #include <rte_pci.h> 8 #include <rte_bus_pci.h> 9 10 #include <octeontx_mbox.h> 11 12 #include "ssovf_evdev.h" 13 #include "timvf_evdev.h" 14 15 #ifndef PCI_VENDOR_ID_CAVIUM 16 #define PCI_VENDOR_ID_CAVIUM (0x177D) 17 #endif 18 19 #define PCI_DEVICE_ID_OCTEONTX_TIM_VF (0xA051) 20 #define TIM_MAX_RINGS (64) 21 22 struct timvf_res { 23 uint16_t domain; 24 uint16_t vfid; 25 void *bar0; 26 void *bar2; 27 void *bar4; 28 }; 29 30 struct timdev { 31 uint8_t total_timvfs; 32 struct timvf_res rings[TIM_MAX_RINGS]; 33 }; 34 35 static struct timdev tdev; 36 37 int 38 timvf_info(struct timvf_info *tinfo) 39 { 40 int i; 41 struct ssovf_info info; 42 43 if (tinfo == NULL) 44 return -EINVAL; 45 46 if (!tdev.total_timvfs) 47 return -ENODEV; 48 49 if (ssovf_info(&info) < 0) 50 return -EINVAL; 51 52 for (i = 0; i < tdev.total_timvfs; i++) { 53 if (info.domain != tdev.rings[i].domain) { 54 timvf_log_err("GRP error, vfid=%d/%d domain=%d/%d %p", 55 i, tdev.rings[i].vfid, 56 info.domain, tdev.rings[i].domain, 57 tdev.rings[i].bar0); 58 return -EINVAL; 59 } 60 } 61 62 tinfo->total_timvfs = tdev.total_timvfs; 63 tinfo->domain = info.domain; 64 return 0; 65 } 66 67 void* 68 timvf_bar(uint8_t id, uint8_t bar) 69 { 70 if (rte_eal_process_type() != RTE_PROC_PRIMARY) 71 return NULL; 72 73 if (id > tdev.total_timvfs) 74 return NULL; 75 76 switch (bar) { 77 case 0: 78 return tdev.rings[id].bar0; 79 case 4: 80 return tdev.rings[id].bar4; 81 default: 82 return NULL; 83 } 84 } 85 86 static int 87 timvf_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev) 88 { 89 uint64_t val; 90 uint16_t vfid; 91 struct timvf_res *res; 92 93 RTE_SET_USED(pci_drv); 94 95 /* For secondary processes, the primary has done all the work */ 96 if (rte_eal_process_type() != RTE_PROC_PRIMARY) 97 return 0; 98 99 if (pci_dev->mem_resource[0].addr == NULL || 100 pci_dev->mem_resource[4].addr == NULL) { 101 timvf_log_err("Empty bars %p %p", 102 pci_dev->mem_resource[0].addr, 103 pci_dev->mem_resource[4].addr); 104 return -ENODEV; 105 } 106 107 val = rte_read64((uint8_t *)pci_dev->mem_resource[0].addr + 108 0x100 /* TIM_VRINGX_BASE */); 109 vfid = (val >> 23) & 0xff; 110 if (vfid >= TIM_MAX_RINGS) { 111 timvf_log_err("Invalid vfid(%d/%d)", vfid, TIM_MAX_RINGS); 112 return -EINVAL; 113 } 114 115 res = &tdev.rings[tdev.total_timvfs]; 116 res->vfid = vfid; 117 res->bar0 = pci_dev->mem_resource[0].addr; 118 res->bar2 = pci_dev->mem_resource[2].addr; 119 res->bar4 = pci_dev->mem_resource[4].addr; 120 res->domain = (val >> 7) & 0xffff; 121 tdev.total_timvfs++; 122 rte_wmb(); 123 124 timvf_log_dbg("Domain=%d VFid=%d bar0 %p total_timvfs=%d", res->domain, 125 res->vfid, pci_dev->mem_resource[0].addr, 126 tdev.total_timvfs); 127 return 0; 128 } 129 130 131 static const struct rte_pci_id pci_timvf_map[] = { 132 { 133 RTE_PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, 134 PCI_DEVICE_ID_OCTEONTX_TIM_VF) 135 }, 136 { 137 .vendor_id = 0, 138 }, 139 }; 140 141 static struct rte_pci_driver pci_timvf = { 142 .id_table = pci_timvf_map, 143 .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_NEED_IOVA_AS_VA, 144 .probe = timvf_probe, 145 .remove = NULL, 146 }; 147 148 RTE_PMD_REGISTER_PCI(octeontx_timvf, pci_timvf); 149