1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2018 Intel Corporation 3 */ 4 5 #include "ifpga_api.h" 6 #include "ifpga_enumerate.h" 7 #include "ifpga_feature_dev.h" 8 9 #include "opae_hw_api.h" 10 11 /* Accelerator APIs */ 12 static int ifpga_acc_get_uuid(struct opae_accelerator *acc, 13 struct uuid *uuid) 14 { 15 struct opae_bridge *br = acc->br; 16 struct ifpga_port_hw *port; 17 18 if (!br || !br->data) 19 return -EINVAL; 20 21 port = br->data; 22 23 return fpga_get_afu_uuid(port, uuid); 24 } 25 26 static int ifpga_acc_set_irq(struct opae_accelerator *acc, 27 u32 start, u32 count, s32 evtfds[]) 28 { 29 struct ifpga_afu_info *afu_info = acc->data; 30 struct opae_bridge *br = acc->br; 31 struct ifpga_port_hw *port; 32 struct fpga_uafu_irq_set irq_set; 33 34 if (!br || !br->data) 35 return -EINVAL; 36 37 if (start >= afu_info->num_irqs || start + count > afu_info->num_irqs) 38 return -EINVAL; 39 40 port = br->data; 41 42 irq_set.start = start; 43 irq_set.count = count; 44 irq_set.evtfds = evtfds; 45 46 return ifpga_set_irq(port->parent, FEATURE_FIU_ID_PORT, port->port_id, 47 IFPGA_PORT_FEATURE_ID_UINT, &irq_set); 48 } 49 50 static int ifpga_acc_get_info(struct opae_accelerator *acc, 51 struct opae_acc_info *info) 52 { 53 struct ifpga_afu_info *afu_info = acc->data; 54 55 if (!afu_info) 56 return -ENODEV; 57 58 info->num_regions = afu_info->num_regions; 59 info->num_irqs = afu_info->num_irqs; 60 61 return 0; 62 } 63 64 static int ifpga_acc_get_region_info(struct opae_accelerator *acc, 65 struct opae_acc_region_info *info) 66 { 67 struct ifpga_afu_info *afu_info = acc->data; 68 69 if (!afu_info) 70 return -EINVAL; 71 72 if (info->index >= afu_info->num_regions) 73 return -EINVAL; 74 75 /* always one RW region only for AFU now */ 76 info->flags = ACC_REGION_READ | ACC_REGION_WRITE | ACC_REGION_MMIO; 77 info->len = afu_info->region[info->index].len; 78 info->addr = afu_info->region[info->index].addr; 79 info->phys_addr = afu_info->region[info->index].phys_addr; 80 81 return 0; 82 } 83 84 static int ifpga_acc_read(struct opae_accelerator *acc, unsigned int region_idx, 85 u64 offset, unsigned int byte, void *data) 86 { 87 struct ifpga_afu_info *afu_info = acc->data; 88 struct opae_reg_region *region; 89 90 if (!afu_info) 91 return -EINVAL; 92 93 if (offset + byte <= offset) 94 return -EINVAL; 95 96 if (region_idx >= afu_info->num_regions) 97 return -EINVAL; 98 99 region = &afu_info->region[region_idx]; 100 if (offset + byte > region->len) 101 return -EINVAL; 102 103 switch (byte) { 104 case 8: 105 *(u64 *)data = opae_readq(region->addr + offset); 106 break; 107 case 4: 108 *(u32 *)data = opae_readl(region->addr + offset); 109 break; 110 case 2: 111 *(u16 *)data = opae_readw(region->addr + offset); 112 break; 113 case 1: 114 *(u8 *)data = opae_readb(region->addr + offset); 115 break; 116 default: 117 return -EINVAL; 118 } 119 120 return 0; 121 } 122 123 static int ifpga_acc_write(struct opae_accelerator *acc, 124 unsigned int region_idx, u64 offset, 125 unsigned int byte, void *data) 126 { 127 struct ifpga_afu_info *afu_info = acc->data; 128 struct opae_reg_region *region; 129 130 if (!afu_info) 131 return -EINVAL; 132 133 if (offset + byte <= offset) 134 return -EINVAL; 135 136 if (region_idx >= afu_info->num_regions) 137 return -EINVAL; 138 139 region = &afu_info->region[region_idx]; 140 if (offset + byte > region->len) 141 return -EINVAL; 142 143 /* normal mmio case */ 144 switch (byte) { 145 case 8: 146 opae_writeq(*(u64 *)data, region->addr + offset); 147 break; 148 case 4: 149 opae_writel(*(u32 *)data, region->addr + offset); 150 break; 151 case 2: 152 opae_writew(*(u16 *)data, region->addr + offset); 153 break; 154 case 1: 155 opae_writeb(*(u8 *)data, region->addr + offset); 156 break; 157 default: 158 return -EINVAL; 159 } 160 161 return 0; 162 } 163 164 struct opae_accelerator_ops ifpga_acc_ops = { 165 .read = ifpga_acc_read, 166 .write = ifpga_acc_write, 167 .set_irq = ifpga_acc_set_irq, 168 .get_info = ifpga_acc_get_info, 169 .get_region_info = ifpga_acc_get_region_info, 170 .get_uuid = ifpga_acc_get_uuid, 171 }; 172 173 /* Bridge APIs */ 174 static int ifpga_br_reset(struct opae_bridge *br) 175 { 176 struct ifpga_port_hw *port = br->data; 177 178 return fpga_port_reset(port); 179 } 180 181 struct opae_bridge_ops ifpga_br_ops = { 182 .reset = ifpga_br_reset, 183 }; 184 185 /* Manager APIs */ 186 static int ifpga_mgr_flash(struct opae_manager *mgr, int id, const char *buf, 187 u32 size, u64 *status) 188 { 189 struct ifpga_fme_hw *fme = mgr->data; 190 struct ifpga_hw *hw = fme->parent; 191 192 return ifpga_pr(hw, id, buf, size, status); 193 } 194 195 static int ifpga_mgr_get_eth_group_region_info(struct opae_manager *mgr, 196 struct opae_eth_group_region_info *info) 197 { 198 struct ifpga_fme_hw *fme = mgr->data; 199 200 if (info->group_id >= MAX_ETH_GROUP_DEVICES) 201 return -EINVAL; 202 203 info->phys_addr = fme->eth_group_region[info->group_id].phys_addr; 204 info->addr = fme->eth_group_region[info->group_id].addr; 205 info->len = fme->eth_group_region[info->group_id].len; 206 207 info->mem_idx = fme->nums_acc_region + info->group_id; 208 209 return 0; 210 } 211 212 struct opae_manager_ops ifpga_mgr_ops = { 213 .flash = ifpga_mgr_flash, 214 .get_eth_group_region_info = ifpga_mgr_get_eth_group_region_info, 215 }; 216 217 static int ifpga_mgr_read_mac_rom(struct opae_manager *mgr, int offset, 218 void *buf, int size) 219 { 220 struct ifpga_fme_hw *fme = mgr->data; 221 222 return fme_mgr_read_mac_rom(fme, offset, buf, size); 223 } 224 225 static int ifpga_mgr_write_mac_rom(struct opae_manager *mgr, int offset, 226 void *buf, int size) 227 { 228 struct ifpga_fme_hw *fme = mgr->data; 229 230 return fme_mgr_write_mac_rom(fme, offset, buf, size); 231 } 232 233 static int ifpga_mgr_get_eth_group_nums(struct opae_manager *mgr) 234 { 235 struct ifpga_fme_hw *fme = mgr->data; 236 237 return fme_mgr_get_eth_group_nums(fme); 238 } 239 240 static int ifpga_mgr_get_eth_group_info(struct opae_manager *mgr, 241 u8 group_id, struct opae_eth_group_info *info) 242 { 243 struct ifpga_fme_hw *fme = mgr->data; 244 245 return fme_mgr_get_eth_group_info(fme, group_id, info); 246 } 247 248 static int ifpga_mgr_eth_group_reg_read(struct opae_manager *mgr, u8 group_id, 249 u8 type, u8 index, u16 addr, u32 *data) 250 { 251 struct ifpga_fme_hw *fme = mgr->data; 252 253 return fme_mgr_eth_group_read_reg(fme, group_id, 254 type, index, addr, data); 255 } 256 257 static int ifpga_mgr_eth_group_reg_write(struct opae_manager *mgr, u8 group_id, 258 u8 type, u8 index, u16 addr, u32 data) 259 { 260 struct ifpga_fme_hw *fme = mgr->data; 261 262 return fme_mgr_eth_group_write_reg(fme, group_id, 263 type, index, addr, data); 264 } 265 266 static int ifpga_mgr_get_retimer_info(struct opae_manager *mgr, 267 struct opae_retimer_info *info) 268 { 269 struct ifpga_fme_hw *fme = mgr->data; 270 271 return fme_mgr_get_retimer_info(fme, info); 272 } 273 274 static int ifpga_mgr_get_retimer_status(struct opae_manager *mgr, 275 struct opae_retimer_status *status) 276 { 277 struct ifpga_fme_hw *fme = mgr->data; 278 279 return fme_mgr_get_retimer_status(fme, status); 280 } 281 282 /* Network APIs in FME */ 283 struct opae_manager_networking_ops ifpga_mgr_network_ops = { 284 .read_mac_rom = ifpga_mgr_read_mac_rom, 285 .write_mac_rom = ifpga_mgr_write_mac_rom, 286 .get_eth_group_nums = ifpga_mgr_get_eth_group_nums, 287 .get_eth_group_info = ifpga_mgr_get_eth_group_info, 288 .eth_group_reg_read = ifpga_mgr_eth_group_reg_read, 289 .eth_group_reg_write = ifpga_mgr_eth_group_reg_write, 290 .get_retimer_info = ifpga_mgr_get_retimer_info, 291 .get_retimer_status = ifpga_mgr_get_retimer_status, 292 }; 293 294 /* Adapter APIs */ 295 static int ifpga_adapter_enumerate(struct opae_adapter *adapter) 296 { 297 struct ifpga_hw *hw = malloc(sizeof(*hw)); 298 299 if (hw) { 300 opae_memset(hw, 0, sizeof(*hw)); 301 hw->pci_data = adapter->data; 302 hw->adapter = adapter; 303 if (ifpga_bus_enumerate(hw)) 304 goto error; 305 return ifpga_bus_init(hw); 306 } 307 308 error: 309 return -ENOMEM; 310 } 311 312 struct opae_adapter_ops ifpga_adapter_ops = { 313 .enumerate = ifpga_adapter_enumerate, 314 }; 315 316 /** 317 * ifpga_pr - do the partial reconfiguration for a given port device 318 * @hw: pointer to the HW structure 319 * @port_id: the port device id 320 * @buffer: the buffer of the bitstream 321 * @size: the size of the bitstream 322 * @status: hardware status including PR error code if return -EIO. 323 * 324 * @return 325 * - 0: Success, partial reconfiguration finished. 326 * - <0: Error code returned in partial reconfiguration. 327 **/ 328 int ifpga_pr(struct ifpga_hw *hw, u32 port_id, const char *buffer, u32 size, 329 u64 *status) 330 { 331 if (!is_valid_port_id(hw, port_id)) 332 return -ENODEV; 333 334 return do_pr(hw, port_id, buffer, size, status); 335 } 336 337 int ifpga_get_prop(struct ifpga_hw *hw, u32 fiu_id, u32 port_id, 338 struct feature_prop *prop) 339 { 340 if (!hw || !prop) 341 return -EINVAL; 342 343 switch (fiu_id) { 344 case FEATURE_FIU_ID_FME: 345 return fme_get_prop(&hw->fme, prop); 346 case FEATURE_FIU_ID_PORT: 347 if (!is_valid_port_id(hw, port_id)) 348 return -ENODEV; 349 return port_get_prop(&hw->port[port_id], prop); 350 } 351 352 return -ENOENT; 353 } 354 355 int ifpga_set_prop(struct ifpga_hw *hw, u32 fiu_id, u32 port_id, 356 struct feature_prop *prop) 357 { 358 if (!hw || !prop) 359 return -EINVAL; 360 361 switch (fiu_id) { 362 case FEATURE_FIU_ID_FME: 363 return fme_set_prop(&hw->fme, prop); 364 case FEATURE_FIU_ID_PORT: 365 if (!is_valid_port_id(hw, port_id)) 366 return -ENODEV; 367 return port_set_prop(&hw->port[port_id], prop); 368 } 369 370 return -ENOENT; 371 } 372 373 int ifpga_set_irq(struct ifpga_hw *hw, u32 fiu_id, u32 port_id, 374 u32 feature_id, void *irq_set) 375 { 376 if (!hw || !irq_set) 377 return -EINVAL; 378 379 switch (fiu_id) { 380 case FEATURE_FIU_ID_FME: 381 return fme_set_irq(&hw->fme, feature_id, irq_set); 382 case FEATURE_FIU_ID_PORT: 383 if (!is_valid_port_id(hw, port_id)) 384 return -ENODEV; 385 return port_set_irq(&hw->port[port_id], feature_id, irq_set); 386 } 387 388 return -ENOENT; 389 } 390