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