1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2017 Cavium, Inc 3 */ 4 5 #include <rte_atomic.h> 6 #include <rte_common.h> 7 #include <rte_eal.h> 8 #include <rte_io.h> 9 #include <rte_pci.h> 10 #include <rte_bus_pci.h> 11 12 #include "octeontx_mbox.h" 13 #include "ssovf_evdev.h" 14 15 #define PCI_VENDOR_ID_CAVIUM 0x177D 16 #define PCI_DEVICE_ID_OCTEONTX_SSOGRP_VF 0xA04B 17 #define PCI_DEVICE_ID_OCTEONTX_SSOWS_VF 0xA04D 18 19 #define SSO_MAX_VHGRP (64) 20 #define SSO_MAX_VHWS (32) 21 22 struct ssovf_res { 23 uint16_t domain; 24 uint16_t vfid; 25 void *bar0; 26 void *bar2; 27 }; 28 29 struct ssowvf_res { 30 uint16_t domain; 31 uint16_t vfid; 32 void *bar0; 33 void *bar2; 34 void *bar4; 35 }; 36 37 struct ssowvf_identify { 38 uint16_t domain; 39 uint16_t vfid; 40 }; 41 42 struct ssodev { 43 uint8_t total_ssovfs; 44 uint8_t total_ssowvfs; 45 struct ssovf_res grp[SSO_MAX_VHGRP]; 46 struct ssowvf_res hws[SSO_MAX_VHWS]; 47 }; 48 49 static struct ssodev sdev; 50 51 /* Interface functions */ 52 int 53 ssovf_info(struct ssovf_info *info) 54 { 55 uint8_t i; 56 uint16_t domain; 57 58 if (rte_eal_process_type() != RTE_PROC_PRIMARY || info == NULL) 59 return -EINVAL; 60 61 if (sdev.total_ssovfs == 0 || sdev.total_ssowvfs == 0) 62 return -ENODEV; 63 64 domain = sdev.grp[0].domain; 65 for (i = 0; i < sdev.total_ssovfs; i++) { 66 /* Check vfid's are contiguous and belong to same domain */ 67 if (sdev.grp[i].vfid != i || 68 sdev.grp[i].bar0 == NULL || 69 sdev.grp[i].domain != domain) { 70 mbox_log_err("GRP error, vfid=%d/%d domain=%d/%d %p", 71 i, sdev.grp[i].vfid, 72 domain, sdev.grp[i].domain, 73 sdev.grp[i].bar0); 74 return -EINVAL; 75 } 76 } 77 78 for (i = 0; i < sdev.total_ssowvfs; i++) { 79 /* Check vfid's are contiguous and belong to same domain */ 80 if (sdev.hws[i].vfid != i || 81 sdev.hws[i].bar0 == NULL || 82 sdev.hws[i].domain != domain) { 83 mbox_log_err("HWS error, vfid=%d/%d domain=%d/%d %p", 84 i, sdev.hws[i].vfid, 85 domain, sdev.hws[i].domain, 86 sdev.hws[i].bar0); 87 return -EINVAL; 88 } 89 } 90 91 info->domain = domain; 92 info->total_ssovfs = sdev.total_ssovfs; 93 info->total_ssowvfs = sdev.total_ssowvfs; 94 return 0; 95 } 96 97 void* 98 ssovf_bar(enum ssovf_type type, uint8_t id, uint8_t bar) 99 { 100 if (rte_eal_process_type() != RTE_PROC_PRIMARY || 101 type > OCTEONTX_SSO_HWS) 102 return NULL; 103 104 if (type == OCTEONTX_SSO_GROUP) { 105 if (id >= sdev.total_ssovfs) 106 return NULL; 107 } else { 108 if (id >= sdev.total_ssowvfs) 109 return NULL; 110 } 111 112 if (type == OCTEONTX_SSO_GROUP) { 113 switch (bar) { 114 case 0: 115 return sdev.grp[id].bar0; 116 case 2: 117 return sdev.grp[id].bar2; 118 default: 119 return NULL; 120 } 121 } else { 122 switch (bar) { 123 case 0: 124 return sdev.hws[id].bar0; 125 case 2: 126 return sdev.hws[id].bar2; 127 case 4: 128 return sdev.hws[id].bar4; 129 default: 130 return NULL; 131 } 132 } 133 } 134 135 /* SSOWVF pcie device aka event port probe */ 136 137 static int 138 ssowvf_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev) 139 { 140 uint16_t vfid; 141 struct ssowvf_res *res; 142 struct ssowvf_identify *id; 143 uint8_t *ram_mbox_base; 144 145 RTE_SET_USED(pci_drv); 146 147 /* For secondary processes, the primary has done all the work */ 148 if (rte_eal_process_type() != RTE_PROC_PRIMARY) 149 return 0; 150 151 if (pci_dev->mem_resource[0].addr == NULL || 152 pci_dev->mem_resource[2].addr == NULL || 153 pci_dev->mem_resource[4].addr == NULL) { 154 mbox_log_err("Empty bars %p %p %p", 155 pci_dev->mem_resource[0].addr, 156 pci_dev->mem_resource[2].addr, 157 pci_dev->mem_resource[4].addr); 158 return -ENODEV; 159 } 160 161 if (pci_dev->mem_resource[4].len != SSOW_BAR4_LEN) { 162 mbox_log_err("Bar4 len mismatch %d != %d", 163 SSOW_BAR4_LEN, (int)pci_dev->mem_resource[4].len); 164 return -EINVAL; 165 } 166 167 id = pci_dev->mem_resource[4].addr; 168 vfid = id->vfid; 169 if (vfid >= SSO_MAX_VHWS) { 170 mbox_log_err("Invalid vfid(%d/%d)", vfid, SSO_MAX_VHWS); 171 return -EINVAL; 172 } 173 174 res = &sdev.hws[vfid]; 175 res->vfid = vfid; 176 res->bar0 = pci_dev->mem_resource[0].addr; 177 res->bar2 = pci_dev->mem_resource[2].addr; 178 res->bar4 = pci_dev->mem_resource[4].addr; 179 res->domain = id->domain; 180 181 sdev.total_ssowvfs++; 182 if (vfid == 0) { 183 ram_mbox_base = ssovf_bar(OCTEONTX_SSO_HWS, 0, 4); 184 if (octeontx_mbox_set_ram_mbox_base(ram_mbox_base, 185 res->domain)) { 186 mbox_log_err("Invalid Failed to set ram mbox base"); 187 return -EINVAL; 188 } 189 } 190 191 rte_wmb(); 192 mbox_log_dbg("Domain=%d hws=%d total_ssowvfs=%d", res->domain, 193 res->vfid, sdev.total_ssowvfs); 194 return 0; 195 } 196 197 static const struct rte_pci_id pci_ssowvf_map[] = { 198 { 199 RTE_PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, 200 PCI_DEVICE_ID_OCTEONTX_SSOWS_VF) 201 }, 202 { 203 .vendor_id = 0, 204 }, 205 }; 206 207 static struct rte_pci_driver pci_ssowvf = { 208 .id_table = pci_ssowvf_map, 209 .drv_flags = RTE_PCI_DRV_NEED_MAPPING, 210 .probe = ssowvf_probe, 211 }; 212 213 RTE_PMD_REGISTER_PCI(octeontx_ssowvf, pci_ssowvf); 214 215 /* SSOVF pcie device aka event queue probe */ 216 217 static int 218 ssovf_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev) 219 { 220 uint64_t val; 221 uint16_t vfid; 222 uint8_t *idreg; 223 struct ssovf_res *res; 224 uint8_t *reg; 225 226 RTE_SET_USED(pci_drv); 227 228 /* For secondary processes, the primary has done all the work */ 229 if (rte_eal_process_type() != RTE_PROC_PRIMARY) 230 return 0; 231 232 if (pci_dev->mem_resource[0].addr == NULL || 233 pci_dev->mem_resource[2].addr == NULL) { 234 mbox_log_err("Empty bars %p %p", 235 pci_dev->mem_resource[0].addr, 236 pci_dev->mem_resource[2].addr); 237 return -ENODEV; 238 } 239 idreg = pci_dev->mem_resource[0].addr; 240 idreg += SSO_VHGRP_AQ_THR; 241 val = rte_read64(idreg); 242 243 /* Write back the default value of aq_thr */ 244 rte_write64((1ULL << 33) - 1, idreg); 245 vfid = (val >> 16) & 0xffff; 246 if (vfid >= SSO_MAX_VHGRP) { 247 mbox_log_err("Invalid vfid (%d/%d)", vfid, SSO_MAX_VHGRP); 248 return -EINVAL; 249 } 250 251 res = &sdev.grp[vfid]; 252 res->vfid = vfid; 253 res->bar0 = pci_dev->mem_resource[0].addr; 254 res->bar2 = pci_dev->mem_resource[2].addr; 255 res->domain = val & 0xffff; 256 257 sdev.total_ssovfs++; 258 if (vfid == 0) { 259 reg = ssovf_bar(OCTEONTX_SSO_GROUP, 0, 0); 260 reg += SSO_VHGRP_PF_MBOX(1); 261 if (octeontx_mbox_set_reg(reg, res->domain)) { 262 mbox_log_err("Invalid Failed to set mbox_reg"); 263 return -EINVAL; 264 } 265 } 266 267 rte_wmb(); 268 mbox_log_dbg("Domain=%d group=%d total_ssovfs=%d", res->domain, 269 res->vfid, sdev.total_ssovfs); 270 return 0; 271 } 272 273 static const struct rte_pci_id pci_ssovf_map[] = { 274 { 275 RTE_PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, 276 PCI_DEVICE_ID_OCTEONTX_SSOGRP_VF) 277 }, 278 { 279 .vendor_id = 0, 280 }, 281 }; 282 283 static struct rte_pci_driver pci_ssovf = { 284 .id_table = pci_ssovf_map, 285 .drv_flags = RTE_PCI_DRV_NEED_MAPPING, 286 .probe = ssovf_probe, 287 }; 288 289 RTE_PMD_REGISTER_PCI(octeontx_ssovf, pci_ssovf); 290