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 static int ifpga_mgr_get_sensor_value(struct opae_manager *mgr, 213 struct opae_sensor_info *sensor, 214 unsigned int *value) 215 { 216 struct ifpga_fme_hw *fme = mgr->data; 217 218 return fme_mgr_get_sensor_value(fme, sensor, value); 219 } 220 221 static int ifpga_mgr_get_board_info(struct opae_manager *mgr, 222 struct opae_board_info **info) 223 { 224 struct ifpga_fme_hw *fme = mgr->data; 225 226 *info = &fme->board_info; 227 228 return 0; 229 } 230 231 struct opae_manager_ops ifpga_mgr_ops = { 232 .flash = ifpga_mgr_flash, 233 .get_eth_group_region_info = ifpga_mgr_get_eth_group_region_info, 234 .get_sensor_value = ifpga_mgr_get_sensor_value, 235 .get_board_info = ifpga_mgr_get_board_info, 236 }; 237 238 static int ifpga_mgr_read_mac_rom(struct opae_manager *mgr, int offset, 239 void *buf, int size) 240 { 241 struct ifpga_fme_hw *fme = mgr->data; 242 243 return fme_mgr_read_mac_rom(fme, offset, buf, size); 244 } 245 246 static int ifpga_mgr_write_mac_rom(struct opae_manager *mgr, int offset, 247 void *buf, int size) 248 { 249 struct ifpga_fme_hw *fme = mgr->data; 250 251 return fme_mgr_write_mac_rom(fme, offset, buf, size); 252 } 253 254 static int ifpga_mgr_get_eth_group_nums(struct opae_manager *mgr) 255 { 256 struct ifpga_fme_hw *fme = mgr->data; 257 258 return fme_mgr_get_eth_group_nums(fme); 259 } 260 261 static int ifpga_mgr_get_eth_group_info(struct opae_manager *mgr, 262 u8 group_id, struct opae_eth_group_info *info) 263 { 264 struct ifpga_fme_hw *fme = mgr->data; 265 266 return fme_mgr_get_eth_group_info(fme, group_id, info); 267 } 268 269 static int ifpga_mgr_eth_group_reg_read(struct opae_manager *mgr, u8 group_id, 270 u8 type, u8 index, u16 addr, u32 *data) 271 { 272 struct ifpga_fme_hw *fme = mgr->data; 273 274 return fme_mgr_eth_group_read_reg(fme, group_id, 275 type, index, addr, data); 276 } 277 278 static int ifpga_mgr_eth_group_reg_write(struct opae_manager *mgr, u8 group_id, 279 u8 type, u8 index, u16 addr, u32 data) 280 { 281 struct ifpga_fme_hw *fme = mgr->data; 282 283 return fme_mgr_eth_group_write_reg(fme, group_id, 284 type, index, addr, data); 285 } 286 287 static int ifpga_mgr_get_retimer_info(struct opae_manager *mgr, 288 struct opae_retimer_info *info) 289 { 290 struct ifpga_fme_hw *fme = mgr->data; 291 292 return fme_mgr_get_retimer_info(fme, info); 293 } 294 295 static int ifpga_mgr_get_retimer_status(struct opae_manager *mgr, 296 struct opae_retimer_status *status) 297 { 298 struct ifpga_fme_hw *fme = mgr->data; 299 300 return fme_mgr_get_retimer_status(fme, status); 301 } 302 303 /* Network APIs in FME */ 304 struct opae_manager_networking_ops ifpga_mgr_network_ops = { 305 .read_mac_rom = ifpga_mgr_read_mac_rom, 306 .write_mac_rom = ifpga_mgr_write_mac_rom, 307 .get_eth_group_nums = ifpga_mgr_get_eth_group_nums, 308 .get_eth_group_info = ifpga_mgr_get_eth_group_info, 309 .eth_group_reg_read = ifpga_mgr_eth_group_reg_read, 310 .eth_group_reg_write = ifpga_mgr_eth_group_reg_write, 311 .get_retimer_info = ifpga_mgr_get_retimer_info, 312 .get_retimer_status = ifpga_mgr_get_retimer_status, 313 }; 314 315 /* Adapter APIs */ 316 static int ifpga_adapter_enumerate(struct opae_adapter *adapter) 317 { 318 struct ifpga_hw *hw = malloc(sizeof(*hw)); 319 320 if (hw) { 321 opae_memset(hw, 0, sizeof(*hw)); 322 hw->pci_data = adapter->data; 323 hw->adapter = adapter; 324 if (ifpga_bus_enumerate(hw)) 325 goto error; 326 return ifpga_bus_init(hw); 327 } 328 329 error: 330 return -ENOMEM; 331 } 332 333 static void ifpga_adapter_destroy(struct opae_adapter *adapter) 334 { 335 struct ifpga_fme_hw *fme; 336 337 if (adapter && adapter->mgr && adapter->mgr->data) { 338 fme = (struct ifpga_fme_hw *)adapter->mgr->data; 339 if (fme->parent) 340 ifpga_bus_uinit(fme->parent); 341 } 342 } 343 344 struct opae_adapter_ops ifpga_adapter_ops = { 345 .enumerate = ifpga_adapter_enumerate, 346 .destroy = ifpga_adapter_destroy, 347 }; 348 349 /** 350 * ifpga_pr - do the partial reconfiguration for a given port device 351 * @hw: pointer to the HW structure 352 * @port_id: the port device id 353 * @buffer: the buffer of the bitstream 354 * @size: the size of the bitstream 355 * @status: hardware status including PR error code if return -EIO. 356 * 357 * @return 358 * - 0: Success, partial reconfiguration finished. 359 * - <0: Error code returned in partial reconfiguration. 360 **/ 361 int ifpga_pr(struct ifpga_hw *hw, u32 port_id, const char *buffer, u32 size, 362 u64 *status) 363 { 364 if (!is_valid_port_id(hw, port_id)) 365 return -ENODEV; 366 367 return do_pr(hw, port_id, buffer, size, status); 368 } 369 370 int ifpga_get_prop(struct ifpga_hw *hw, u32 fiu_id, u32 port_id, 371 struct feature_prop *prop) 372 { 373 if (!hw || !prop) 374 return -EINVAL; 375 376 switch (fiu_id) { 377 case FEATURE_FIU_ID_FME: 378 return fme_get_prop(&hw->fme, prop); 379 case FEATURE_FIU_ID_PORT: 380 if (!is_valid_port_id(hw, port_id)) 381 return -ENODEV; 382 return port_get_prop(&hw->port[port_id], prop); 383 } 384 385 return -ENOENT; 386 } 387 388 int ifpga_set_prop(struct ifpga_hw *hw, u32 fiu_id, u32 port_id, 389 struct feature_prop *prop) 390 { 391 if (!hw || !prop) 392 return -EINVAL; 393 394 switch (fiu_id) { 395 case FEATURE_FIU_ID_FME: 396 return fme_set_prop(&hw->fme, prop); 397 case FEATURE_FIU_ID_PORT: 398 if (!is_valid_port_id(hw, port_id)) 399 return -ENODEV; 400 return port_set_prop(&hw->port[port_id], prop); 401 } 402 403 return -ENOENT; 404 } 405 406 int ifpga_set_irq(struct ifpga_hw *hw, u32 fiu_id, u32 port_id, 407 u32 feature_id, void *irq_set) 408 { 409 if (!hw || !irq_set) 410 return -EINVAL; 411 412 switch (fiu_id) { 413 case FEATURE_FIU_ID_FME: 414 return fme_set_irq(&hw->fme, feature_id, irq_set); 415 case FEATURE_FIU_ID_PORT: 416 if (!is_valid_port_id(hw, port_id)) 417 return -ENODEV; 418 return port_set_irq(&hw->port[port_id], feature_id, irq_set); 419 } 420 421 return -ENOENT; 422 } 423