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